@cakemail-org/cakemail-cli 1.5.0 → 2.0.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 (234) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.env.example +40 -0
  3. package/.env.test.example +45 -0
  4. package/CHANGELOG.md +1031 -0
  5. package/README.md +319 -15
  6. package/audit-formats.js +128 -0
  7. package/cakemail.rb +20 -0
  8. package/dist/cli.js +27 -10
  9. package/dist/cli.js.map +1 -1
  10. package/dist/client.d.ts +2 -0
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +16 -6
  13. package/dist/client.js.map +1 -1
  14. package/dist/commands/account.js +1 -1
  15. package/dist/commands/account.js.map +1 -1
  16. package/dist/commands/attributes.js +1 -1
  17. package/dist/commands/attributes.js.map +1 -1
  18. package/dist/commands/campaigns.d.ts.map +1 -1
  19. package/dist/commands/campaigns.js +103 -8
  20. package/dist/commands/campaigns.js.map +1 -1
  21. package/dist/commands/config.d.ts.map +1 -1
  22. package/dist/commands/config.js +63 -4
  23. package/dist/commands/config.js.map +1 -1
  24. package/dist/commands/contacts.d.ts.map +1 -1
  25. package/dist/commands/contacts.js +91 -12
  26. package/dist/commands/contacts.js.map +1 -1
  27. package/dist/commands/emails.js +1 -1
  28. package/dist/commands/emails.js.map +1 -1
  29. package/dist/commands/interests.d.ts +5 -0
  30. package/dist/commands/interests.d.ts.map +1 -0
  31. package/dist/commands/interests.js +172 -0
  32. package/dist/commands/interests.js.map +1 -0
  33. package/dist/commands/lists.d.ts.map +1 -1
  34. package/dist/commands/lists.js +6 -8
  35. package/dist/commands/lists.js.map +1 -1
  36. package/dist/commands/logs.d.ts +5 -0
  37. package/dist/commands/logs.d.ts.map +1 -0
  38. package/dist/commands/logs.js +237 -0
  39. package/dist/commands/logs.js.map +1 -0
  40. package/dist/commands/reports.js +1 -1
  41. package/dist/commands/reports.js.map +1 -1
  42. package/dist/commands/segments.js +1 -1
  43. package/dist/commands/segments.js.map +1 -1
  44. package/dist/commands/senders.d.ts.map +1 -1
  45. package/dist/commands/senders.js +11 -8
  46. package/dist/commands/senders.js.map +1 -1
  47. package/dist/commands/suppressed.js +1 -1
  48. package/dist/commands/suppressed.js.map +1 -1
  49. package/dist/commands/tags.d.ts +5 -0
  50. package/dist/commands/tags.d.ts.map +1 -0
  51. package/dist/commands/tags.js +124 -0
  52. package/dist/commands/tags.js.map +1 -0
  53. package/dist/commands/templates.js +1 -1
  54. package/dist/commands/templates.js.map +1 -1
  55. package/dist/commands/transactional-templates.d.ts +5 -0
  56. package/dist/commands/transactional-templates.d.ts.map +1 -0
  57. package/dist/commands/transactional-templates.js +354 -0
  58. package/dist/commands/transactional-templates.js.map +1 -0
  59. package/dist/commands/webhooks.js +1 -1
  60. package/dist/commands/webhooks.js.map +1 -1
  61. package/dist/utils/auth.d.ts +8 -1
  62. package/dist/utils/auth.d.ts.map +1 -1
  63. package/dist/utils/auth.js +39 -11
  64. package/dist/utils/auth.js.map +1 -1
  65. package/dist/utils/config-file.d.ts +7 -0
  66. package/dist/utils/config-file.d.ts.map +1 -1
  67. package/dist/utils/config-file.js +15 -0
  68. package/dist/utils/config-file.js.map +1 -1
  69. package/dist/utils/config.d.ts +2 -0
  70. package/dist/utils/config.d.ts.map +1 -1
  71. package/dist/utils/config.js +12 -4
  72. package/dist/utils/config.js.map +1 -1
  73. package/dist/utils/errors.js +1 -1
  74. package/dist/utils/errors.js.map +1 -1
  75. package/dist/utils/list-defaults.d.ts +33 -0
  76. package/dist/utils/list-defaults.d.ts.map +1 -0
  77. package/dist/utils/list-defaults.js +52 -0
  78. package/dist/utils/list-defaults.js.map +1 -0
  79. package/dist/utils/output.d.ts.map +1 -1
  80. package/dist/utils/output.js +36 -13
  81. package/dist/utils/output.js.map +1 -1
  82. package/dist/utils/progress.d.ts.map +1 -1
  83. package/dist/utils/progress.js +32 -4
  84. package/dist/utils/progress.js.map +1 -1
  85. package/dist/utils/spinner.d.ts +17 -0
  86. package/dist/utils/spinner.d.ts.map +1 -0
  87. package/dist/utils/spinner.js +43 -0
  88. package/dist/utils/spinner.js.map +1 -0
  89. package/docs/DOCUMENTATION-STANDARD.md +1068 -0
  90. package/docs/README.md +161 -0
  91. package/docs/developer/ARCHITECTURE.md +516 -0
  92. package/docs/developer/AUTH.md +204 -0
  93. package/docs/developer/CONTRIBUTING.md +227 -0
  94. package/docs/developer/DOCUMENTATION_SUMMARY.md +346 -0
  95. package/docs/developer/PROJECT_INDEX.md +365 -0
  96. package/docs/planning/API_COVERAGE.md +1045 -0
  97. package/docs/planning/BACKLOG.md +1159 -0
  98. package/docs/planning/PROFILE_SYSTEM_TASKS.md +287 -0
  99. package/docs/planning/UX_IMPLEMENTATION_PLAN.md +691 -0
  100. package/docs/planning/archive/RELEASE_CHECKLIST_v1.3.0.md +332 -0
  101. package/docs/planning/archive/RELEASE_v1.3.0.md +428 -0
  102. package/docs/planning/archive/cakemail-cli-ux-improvements.md +438 -0
  103. package/docs/planning/cakemail-profile-system-plan.md +1121 -0
  104. package/docs/testing/AI_USER_SIMULATION_DESIGN.md +1342 -0
  105. package/docs/testing/KENOGAMI_BIDIRECTIONAL_FLOW.md +1517 -0
  106. package/docs/testing/KENOGAMI_TRUTH_RECONCILIATION_SYSTEM.md +1369 -0
  107. package/docs/user-manual/.obsidian/app.json +1 -0
  108. package/docs/user-manual/.obsidian/appearance.json +1 -0
  109. package/docs/user-manual/.obsidian/core-plugins.json +33 -0
  110. package/docs/user-manual/.obsidian/workspace.json +167 -0
  111. package/docs/user-manual/01-getting-started/01-installation.md +214 -0
  112. package/docs/user-manual/01-getting-started/02-quick-start.md +432 -0
  113. package/docs/user-manual/01-getting-started/03-authentication.md +448 -0
  114. package/docs/user-manual/01-getting-started/04-configuration.md +430 -0
  115. package/docs/user-manual/01-getting-started/05-output-formats.md +447 -0
  116. package/docs/user-manual/02-core-concepts/01-accounts.md +514 -0
  117. package/docs/user-manual/02-core-concepts/02-profile-system.md +771 -0
  118. package/docs/user-manual/02-core-concepts/03-smart-defaults.md +485 -0
  119. package/docs/user-manual/02-core-concepts/04-authentication-methods.md +435 -0
  120. package/docs/user-manual/02-core-concepts/05-pagination-filtering.md +600 -0
  121. package/docs/user-manual/02-core-concepts/06-error-handling.md +718 -0
  122. package/docs/user-manual/02-core-concepts/07-api-coverage.md +483 -0
  123. package/docs/user-manual/03-email-operations/01-senders.md +490 -0
  124. package/docs/user-manual/03-email-operations/02-templates.md +444 -0
  125. package/docs/user-manual/03-email-operations/03-transactional-emails.md +706 -0
  126. package/docs/user-manual/03-email-operations/04-email-tracking.md +407 -0
  127. package/docs/user-manual/04-campaign-management/01-campaigns-basics.md +394 -0
  128. package/docs/user-manual/04-campaign-management/02-campaign-scheduling.md +630 -0
  129. package/docs/user-manual/04-campaign-management/03-campaign-testing.md +997 -0
  130. package/docs/user-manual/04-campaign-management/04-campaign-lifecycle.md +709 -0
  131. package/docs/user-manual/04-campaign-management/05-campaign-links.md +934 -0
  132. package/docs/user-manual/05-contact-management/01-lists.md +836 -0
  133. package/docs/user-manual/05-contact-management/02-contacts.md +1035 -0
  134. package/docs/user-manual/05-contact-management/03-custom-attributes.md +788 -0
  135. package/docs/user-manual/05-contact-management/04-segments.md +1028 -0
  136. package/docs/user-manual/05-contact-management/05-contact-import-export.md +1031 -0
  137. package/docs/user-manual/06-analytics-reporting/01-campaign-analytics.md +867 -0
  138. package/docs/user-manual/06-analytics-reporting/02-account-reports.md +227 -0
  139. package/docs/user-manual/07-integrations/01-webhooks-integration.md +259 -0
  140. package/docs/user-manual/07-integrations/02-automation.md +326 -0
  141. package/docs/user-manual/08-advanced-usage/01-scripting-patterns.md +672 -0
  142. package/docs/user-manual/08-advanced-usage/02-bulk-operations.md +932 -0
  143. package/docs/user-manual/08-advanced-usage/03-ci-cd-integration.md +892 -0
  144. package/docs/user-manual/08-advanced-usage/04-performance-optimization.md +766 -0
  145. package/docs/user-manual/09-command-reference/01-config.md +776 -0
  146. package/docs/user-manual/09-command-reference/02-account.md +652 -0
  147. package/docs/user-manual/09-command-reference/03-lists.md +958 -0
  148. package/docs/user-manual/09-command-reference/04-contacts.md +1408 -0
  149. package/docs/user-manual/09-command-reference/05-attributes.md +617 -0
  150. package/docs/user-manual/09-command-reference/06-segments.md +894 -0
  151. package/docs/user-manual/09-command-reference/07-senders.md +803 -0
  152. package/docs/user-manual/09-command-reference/08-templates.md +818 -0
  153. package/docs/user-manual/09-command-reference/09-campaigns.md +1250 -0
  154. package/docs/user-manual/09-command-reference/10-emails.md +807 -0
  155. package/docs/user-manual/09-command-reference/11-reports.md +1135 -0
  156. package/docs/user-manual/09-command-reference/12-webhooks.md +773 -0
  157. package/docs/user-manual/09-command-reference/13-suppressed.md +797 -0
  158. package/docs/user-manual/09-command-reference/14-interests.md +630 -0
  159. package/docs/user-manual/09-command-reference/15-tags.md +584 -0
  160. package/docs/user-manual/09-command-reference/16-logs.md +656 -0
  161. package/docs/user-manual/09-command-reference/17-transactional-templates.md +850 -0
  162. package/docs/user-manual/10-troubleshooting/01-common-errors.md +457 -0
  163. package/docs/user-manual/10-troubleshooting/02-authentication-issues.md +558 -0
  164. package/docs/user-manual/10-troubleshooting/03-connection-problems.md +634 -0
  165. package/docs/user-manual/10-troubleshooting/04-debugging.md +725 -0
  166. package/docs/user-manual/11-appendix/04-faq.md +484 -0
  167. package/docs/user-manual/11-appendix/05-glossary.md +250 -0
  168. package/docs/user-manual/README.md +0 -0
  169. package/package.json +13 -47
  170. package/src/cli.ts +125 -0
  171. package/src/client.ts +16 -0
  172. package/src/commands/account.ts +267 -0
  173. package/src/commands/accounts.ts +78 -0
  174. package/src/commands/actions.ts +249 -0
  175. package/src/commands/attributes.ts +139 -0
  176. package/src/commands/campaign-blueprints.ts +106 -0
  177. package/src/commands/campaigns.ts +469 -0
  178. package/src/commands/config.ts +77 -0
  179. package/src/commands/contacts.ts +612 -0
  180. package/src/commands/custom-attributes.ts +127 -0
  181. package/src/commands/dkims.ts +117 -0
  182. package/src/commands/domains.ts +82 -0
  183. package/src/commands/email-apis.ts +569 -0
  184. package/src/commands/emails.ts +197 -0
  185. package/src/commands/forms.ts +283 -0
  186. package/src/commands/interests.ts +155 -0
  187. package/src/commands/links.ts +38 -0
  188. package/src/commands/lists.ts +406 -0
  189. package/src/commands/logos.ts +71 -0
  190. package/src/commands/logs.ts +386 -0
  191. package/src/commands/reports.ts +306 -0
  192. package/src/commands/segments.ts +158 -0
  193. package/src/commands/senders.ts +204 -0
  194. package/src/commands/sub-accounts.ts +271 -0
  195. package/src/commands/suppressed-emails.ts +234 -0
  196. package/src/commands/suppressed.ts +198 -0
  197. package/src/commands/system-emails.ts +85 -0
  198. package/src/commands/tags.ts +146 -0
  199. package/src/commands/tasks.ts +116 -0
  200. package/src/commands/templates.ts +189 -0
  201. package/src/commands/tokens.ts +83 -0
  202. package/src/commands/transactional-emails.ts +374 -0
  203. package/src/commands/transactional-templates.ts +385 -0
  204. package/src/commands/users.ts +506 -0
  205. package/src/commands/webhooks.ts +172 -0
  206. package/src/commands/workflow-blueprints.ts +123 -0
  207. package/src/commands/workflows.ts +265 -0
  208. package/src/types/profile.ts +93 -0
  209. package/src/utils/auth.ts +272 -0
  210. package/src/utils/config-file.ts +96 -0
  211. package/src/utils/config.ts +134 -0
  212. package/src/utils/confirm.ts +32 -0
  213. package/src/utils/defaults.ts +99 -0
  214. package/src/utils/errors.ts +116 -0
  215. package/src/utils/interactive.ts +91 -0
  216. package/src/utils/list-defaults.ts +74 -0
  217. package/src/utils/output.ts +190 -0
  218. package/src/utils/progress.ts +320 -0
  219. package/src/utils/spinner.ts +22 -0
  220. package/tests/IMPLEMENTATION_STATUS.md +258 -0
  221. package/tests/PTY_SETUP.md +118 -0
  222. package/tests/PTY_TESTING_GUIDE.md +507 -0
  223. package/tests/README.md +244 -0
  224. package/tests/fixtures/api-responses/campaigns.json +34 -0
  225. package/tests/fixtures/test-config.json +13 -0
  226. package/tests/helpers/cli-runner.ts +128 -0
  227. package/tests/helpers/mock-server.ts +301 -0
  228. package/tests/helpers/pty-runner.ts +181 -0
  229. package/tests/integration/campaigns-real-api.test.ts +196 -0
  230. package/tests/integration/setup-integration.ts +50 -0
  231. package/tests/pty/campaigns.test.ts +241 -0
  232. package/tests/setup.ts +34 -0
  233. package/tsconfig.json +15 -0
  234. package/vitest.config.ts +28 -0
@@ -0,0 +1,836 @@
1
+ # Managing Contact Lists
2
+
3
+ Master contact list management for organizing and segmenting your email subscribers.
4
+
5
+ ## Overview
6
+
7
+ Contact lists allow you to:
8
+ - Organize subscribers by audience type
9
+ - Separate marketing campaigns
10
+ - Manage different product lines or brands
11
+ - Maintain compliance with consent requirements
12
+ - Control who receives which campaigns
13
+ - Track list-specific metrics
14
+
15
+ Lists are the foundation of contact management in Cakemail - every contact must belong to at least one list.
16
+
17
+ ## Quick Start
18
+
19
+ ### Create Your First List
20
+
21
+ ```bash
22
+ $ cakemail lists create -n "Newsletter Subscribers" -l "en"
23
+ ```
24
+
25
+ **Output:**
26
+ ```
27
+ ✓ List created successfully
28
+
29
+ ID: 123
30
+ Name: Newsletter Subscribers
31
+ Language: en
32
+ Status: active
33
+ Contacts: 0
34
+ ```
35
+
36
+ ### View All Lists
37
+
38
+ ```bash
39
+ $ cakemail lists list
40
+ ```
41
+
42
+ **Output:**
43
+ ```
44
+ ┌─────┬────────────────────────┬──────────┬───────────┬─────────────────────┐
45
+ │ ID │ Name │ Language │ Contacts │ Created │
46
+ ├─────┼────────────────────────┼──────────┼───────────┼─────────────────────┤
47
+ │ 123 │ Newsletter Subscribers │ en │ 1,247 │ 2024-01-15 10:30:00 │
48
+ │ 124 │ Product Updates │ en │ 856 │ 2024-02-01 14:20:00 │
49
+ │ 125 │ VIP Customers │ en │ 342 │ 2024-03-10 09:00:00 │
50
+ └─────┴────────────────────────┴──────────┴───────────┴─────────────────────┘
51
+ ```
52
+
53
+ ## List Management Basics
54
+
55
+ ### Create a List
56
+
57
+ ```bash
58
+ $ cakemail lists create -n "Monthly Newsletter" -l "en"
59
+ ```
60
+
61
+ **With optional description:**
62
+ ```bash
63
+ $ cakemail lists create \
64
+ -n "Product Announcements" \
65
+ -l "en" \
66
+ -d "Subscribers interested in product updates"
67
+ ```
68
+
69
+ **French language list:**
70
+ ```bash
71
+ $ cakemail lists create -n "Infolettre" -l "fr"
72
+ ```
73
+
74
+ ### View List Details
75
+
76
+ ```bash
77
+ $ cakemail lists get 123
78
+ ```
79
+
80
+ **Output:**
81
+ ```
82
+ {
83
+ "id": 123,
84
+ "name": "Newsletter Subscribers",
85
+ "language": "en",
86
+ "description": "Monthly newsletter subscribers",
87
+ "status": "active",
88
+ "contacts_count": 1247,
89
+ "active_contacts": 1189,
90
+ "unsubscribed": 45,
91
+ "bounced": 13,
92
+ "created_at": "2024-01-15T10:30:00Z",
93
+ "updated_at": "2024-03-15T14:22:00Z"
94
+ }
95
+ ```
96
+
97
+ ### Update List
98
+
99
+ ```bash
100
+ # Update name
101
+ $ cakemail lists update 123 -n "Weekly Newsletter"
102
+
103
+ # Update description
104
+ $ cakemail lists update 123 -d "Weekly updates for subscribers"
105
+
106
+ # Update both
107
+ $ cakemail lists update 123 \
108
+ -n "Newsletter - Weekly Edition" \
109
+ -d "Our weekly newsletter with industry insights"
110
+ ```
111
+
112
+ ### Delete List
113
+
114
+ ```bash
115
+ $ cakemail lists delete 123
116
+ ```
117
+
118
+ **Output:**
119
+ ```
120
+ ⚠ Delete list 123?
121
+
122
+ The following will happen:
123
+ • List and all contacts will be deleted
124
+ • This action cannot be undone
125
+ • Associated campaigns remain but will show "List Deleted"
126
+
127
+ Type 'yes' to confirm: yes
128
+
129
+ ✓ List 123 deleted
130
+ ```
131
+
132
+ **Force delete (skip confirmation):**
133
+ ```bash
134
+ $ cakemail lists delete 123 --force
135
+ ```
136
+
137
+ ## List Organization Strategies
138
+
139
+ ### Strategy 1: By Audience Type
140
+
141
+ ```bash
142
+ # Create lists for different audiences
143
+ $ cakemail lists create -n "B2B Subscribers" -l "en"
144
+ $ cakemail lists create -n "B2C Customers" -l "en"
145
+ $ cakemail lists create -n "Partners & Affiliates" -l "en"
146
+ $ cakemail lists create -n "Internal Team" -l "en"
147
+ ```
148
+
149
+ **Use cases:**
150
+ - Different content for each audience
151
+ - Separate sender addresses
152
+ - Varied sending frequency
153
+ - Audience-specific compliance needs
154
+
155
+ ### Strategy 2: By Product/Brand
156
+
157
+ ```bash
158
+ # Multi-product company
159
+ $ cakemail lists create -n "Product A Users" -l "en"
160
+ $ cakemail lists create -n "Product B Users" -l "en"
161
+ $ cakemail lists create -n "Product C Users" -l "en"
162
+
163
+ # Multi-brand
164
+ $ cakemail lists create -n "Brand X Subscribers" -l "en"
165
+ $ cakemail lists create -n "Brand Y Subscribers" -l "en"
166
+ ```
167
+
168
+ **Use cases:**
169
+ - Separate branding per product
170
+ - Product-specific campaigns
171
+ - Cross-sell opportunities
172
+ - Brand-specific metrics
173
+
174
+ ### Strategy 3: By Engagement Level
175
+
176
+ ```bash
177
+ # Segment by engagement
178
+ $ cakemail lists create -n "Highly Engaged" -l "en"
179
+ $ cakemail lists create -n "Moderately Engaged" -l "en"
180
+ $ cakemail lists create -n "At Risk - Low Engagement" -l "en"
181
+ $ cakemail lists create -n "Re-engagement Candidates" -l "en"
182
+ ```
183
+
184
+ **Use cases:**
185
+ - Engagement-based sending frequency
186
+ - Re-engagement campaigns
187
+ - VIP/loyalty programs
188
+ - List health maintenance
189
+
190
+ ### Strategy 4: By Content Type
191
+
192
+ ```bash
193
+ # Content-based lists
194
+ $ cakemail lists create -n "Blog Subscribers" -l "en"
195
+ $ cakemail lists create -n "Product News" -l "en"
196
+ $ cakemail lists create -n "Event Announcements" -l "en"
197
+ $ cakemail lists create -n "Sales & Promotions" -l "en"
198
+ ```
199
+
200
+ **Use cases:**
201
+ - Content preference management
202
+ - Targeted content delivery
203
+ - Reduced unsubscribes
204
+ - Better engagement rates
205
+
206
+ ### Strategy 5: By Lifecycle Stage
207
+
208
+ ```bash
209
+ # Customer lifecycle
210
+ $ cakemail lists create -n "Leads - Not Converted" -l "en"
211
+ $ cakemail lists create -n "Trial Users" -l "en"
212
+ $ cakemail lists create -n "New Customers (< 30 days)" -l "en"
213
+ $ cakemail lists create -n "Active Customers" -l "en"
214
+ $ cakemail lists create -n "Lapsed Customers" -l "en"
215
+ ```
216
+
217
+ **Use cases:**
218
+ - Lifecycle-specific messaging
219
+ - Onboarding sequences
220
+ - Retention campaigns
221
+ - Win-back campaigns
222
+
223
+ ## List Workflows
224
+
225
+ ### Workflow 1: New Business Setup
226
+
227
+ ```bash
228
+ #!/bin/bash
229
+ # setup-lists.sh
230
+
231
+ echo "=== Setting Up Marketing Lists ==="
232
+ echo ""
233
+
234
+ # Main newsletter
235
+ NEWSLETTER=$(cakemail lists create \
236
+ -n "Newsletter Subscribers" \
237
+ -l "en" \
238
+ -d "Our monthly newsletter" \
239
+ -f json | jq -r '.id')
240
+
241
+ echo "✓ Newsletter list created: $NEWSLETTER"
242
+
243
+ # Product updates
244
+ PRODUCT=$(cakemail lists create \
245
+ -n "Product Updates" \
246
+ -l "en" \
247
+ -d "Product announcements and feature releases" \
248
+ -f json | jq -r '.id')
249
+
250
+ echo "✓ Product updates list created: $PRODUCT"
251
+
252
+ # Promotions
253
+ PROMO=$(cakemail lists create \
254
+ -n "Sales & Promotions" \
255
+ -l "en" \
256
+ -d "Special offers and discounts" \
257
+ -f json | jq -r '.id')
258
+
259
+ echo "✓ Promotions list created: $PROMO"
260
+
261
+ echo ""
262
+ echo "=== Setup Complete ===="
263
+ echo ""
264
+ echo "List IDs:"
265
+ echo " Newsletter: $NEWSLETTER"
266
+ echo " Product Updates: $PRODUCT"
267
+ echo " Promotions: $PROMO"
268
+ echo ""
269
+ echo "Next steps:"
270
+ echo " 1. Import contacts: cakemail contacts import $NEWSLETTER --file contacts.csv"
271
+ echo " 2. Create custom attributes: cakemail attributes create $NEWSLETTER -n \"preference\" -t \"text\""
272
+ echo " 3. Create segments: cakemail segments create $NEWSLETTER -n \"Active Users\""
273
+ ```
274
+
275
+ ### Workflow 2: Multi-Language Support
276
+
277
+ ```bash
278
+ #!/bin/bash
279
+ # multilang-lists.sh
280
+
281
+ echo "=== Creating Multi-Language Lists ==="
282
+ echo ""
283
+
284
+ # English
285
+ EN=$(cakemail lists create \
286
+ -n "Newsletter - English" \
287
+ -l "en" \
288
+ -d "English language newsletter" \
289
+ -f json | jq -r '.id')
290
+
291
+ echo "✓ English list created: $EN"
292
+
293
+ # French
294
+ FR=$(cakemail lists create \
295
+ -n "Newsletter - Français" \
296
+ -l "fr" \
297
+ -d "Infolettre en français" \
298
+ -f json | jq -r '.id')
299
+
300
+ echo "✓ French list created: $FR"
301
+
302
+ # Spanish
303
+ ES=$(cakemail lists create \
304
+ -n "Newsletter - Español" \
305
+ -l "es" \
306
+ -d "Boletín en español" \
307
+ -f json | jq -r '.id')
308
+
309
+ echo "✓ Spanish list created: $ES"
310
+
311
+ echo ""
312
+ echo "Language-specific lists ready"
313
+ echo " English (en): $EN"
314
+ echo " French (fr): $FR"
315
+ echo " Spanish (es): $ES"
316
+ ```
317
+
318
+ ### Workflow 3: List Health Audit
319
+
320
+ ```bash
321
+ #!/bin/bash
322
+ # list-health-audit.sh
323
+
324
+ echo "=== List Health Audit ==="
325
+ echo ""
326
+
327
+ # Get all lists
328
+ LISTS=$(cakemail lists list -f json | jq -r '.data[].id')
329
+
330
+ echo "List ID | Name | Total | Active | Unsub | Bounce | Health"
331
+ echo "--------|------|-------|--------|-------|--------|-------"
332
+
333
+ for LIST_ID in $LISTS; do
334
+ LIST=$(cakemail lists get $LIST_ID -f json)
335
+
336
+ NAME=$(echo "$LIST" | jq -r '.name' | cut -c1-15)
337
+ TOTAL=$(echo "$LIST" | jq -r '.contacts_count')
338
+ ACTIVE=$(echo "$LIST" | jq -r '.active_contacts')
339
+ UNSUB=$(echo "$LIST" | jq -r '.unsubscribed')
340
+ BOUNCE=$(echo "$LIST" | jq -r '.bounced')
341
+
342
+ # Calculate health score
343
+ if [ $TOTAL -gt 0 ]; then
344
+ HEALTH=$(echo "scale=1; $ACTIVE * 100 / $TOTAL" | bc)
345
+ else
346
+ HEALTH="N/A"
347
+ fi
348
+
349
+ printf "%-7s | %-15s | %5d | %6d | %5d | %6d | %s%%\n" \
350
+ "$LIST_ID" "$NAME" "$TOTAL" "$ACTIVE" "$UNSUB" "$BOUNCE" "$HEALTH"
351
+ done
352
+
353
+ echo ""
354
+ echo "Health Score: % of contacts that are active (not unsubscribed or bounced)"
355
+ echo " > 90%: Excellent"
356
+ echo " 80-90%: Good"
357
+ echo " 70-80%: Fair - Consider list cleaning"
358
+ echo " < 70%: Poor - Clean list immediately"
359
+ ```
360
+
361
+ ### Workflow 4: List Consolidation
362
+
363
+ ```bash
364
+ #!/bin/bash
365
+ # consolidate-lists.sh
366
+
367
+ SOURCE_LIST_1=123
368
+ SOURCE_LIST_2=124
369
+ TARGET_LIST=125
370
+
371
+ echo "=== Consolidating Lists ==="
372
+ echo ""
373
+ echo "Merging lists $SOURCE_LIST_1 and $SOURCE_LIST_2 into $TARGET_LIST"
374
+ echo ""
375
+
376
+ # Export contacts from source lists
377
+ echo "Exporting from list $SOURCE_LIST_1..."
378
+ cakemail contacts export $SOURCE_LIST_1
379
+ EXPORT_1=$(cakemail contacts export-list -f json | jq -r '.data[0].id')
380
+
381
+ echo "Exporting from list $SOURCE_LIST_2..."
382
+ cakemail contacts export $SOURCE_LIST_2
383
+ EXPORT_2=$(cakemail contacts export-list -f json | jq -r '.data[0].id')
384
+
385
+ # Wait for exports
386
+ echo "Waiting for exports to complete..."
387
+ sleep 10
388
+
389
+ # Download exports
390
+ cakemail contacts export-download $EXPORT_1 > list1.csv
391
+ cakemail contacts export-download $EXPORT_2 > list2.csv
392
+
393
+ # Combine and deduplicate
394
+ echo "Combining and deduplicating..."
395
+ cat list1.csv list2.csv | sort -u -t',' -k1,1 > combined.csv
396
+
397
+ # Import to target list
398
+ echo "Importing to target list $TARGET_LIST..."
399
+ cakemail contacts import $TARGET_LIST --file combined.csv
400
+
401
+ echo ""
402
+ echo "✓ Lists consolidated"
403
+ echo ""
404
+ read -p "Delete source lists? (yes/no): " DELETE
405
+
406
+ if [ "$DELETE" == "yes" ]; then
407
+ cakemail lists delete $SOURCE_LIST_1 --force
408
+ cakemail lists delete $SOURCE_LIST_2 --force
409
+ echo "✓ Source lists deleted"
410
+ fi
411
+
412
+ # Cleanup
413
+ rm list1.csv list2.csv combined.csv
414
+ ```
415
+
416
+ ### Workflow 5: List Cleanup
417
+
418
+ ```bash
419
+ #!/bin/bash
420
+ # cleanup-list.sh
421
+
422
+ LIST_ID=$1
423
+
424
+ if [ -z "$LIST_ID" ]; then
425
+ echo "Usage: $0 <list-id>"
426
+ exit 1
427
+ fi
428
+
429
+ echo "=== List Cleanup: $LIST_ID ==="
430
+ echo ""
431
+
432
+ # Get list stats
433
+ LIST=$(cakemail lists get $LIST_ID -f json)
434
+ TOTAL=$(echo "$LIST" | jq -r '.contacts_count')
435
+ BOUNCED=$(echo "$LIST" | jq -r '.bounced')
436
+ UNSUB=$(echo "$LIST" | jq -r '.unsubscribed')
437
+
438
+ echo "Current Stats:"
439
+ echo " Total Contacts: $TOTAL"
440
+ echo " Bounced: $BOUNCED"
441
+ echo " Unsubscribed: $UNSUB"
442
+ echo ""
443
+
444
+ # Calculate to remove
445
+ TO_REMOVE=$((BOUNCED + UNSUB))
446
+ echo "Contacts to remove: $TO_REMOVE"
447
+ echo ""
448
+
449
+ read -p "Remove bounced and unsubscribed contacts? (yes/no): " CONFIRM
450
+
451
+ if [ "$CONFIRM" == "yes" ]; then
452
+ echo ""
453
+ echo "Removing bounced contacts..."
454
+ # Export active only, then re-import (effective cleanup)
455
+ cakemail contacts export $LIST_ID --filter "status==subscribed"
456
+
457
+ EXPORT_ID=$(cakemail contacts export-list -f json | jq -r '.data[0].id')
458
+
459
+ echo "Waiting for export..."
460
+ sleep 10
461
+
462
+ # Download clean list
463
+ cakemail contacts export-download $EXPORT_ID > clean.csv
464
+
465
+ # Create new list
466
+ NEW_LIST=$(cakemail lists create \
467
+ -n "$(echo "$LIST" | jq -r '.name') (Cleaned)" \
468
+ -l "$(echo "$LIST" | jq -r '.language')" \
469
+ -f json | jq -r '.id')
470
+
471
+ # Import clean contacts
472
+ echo "Importing clean contacts to new list $NEW_LIST..."
473
+ cakemail contacts import $NEW_LIST --file clean.csv
474
+
475
+ echo ""
476
+ echo "✓ Cleanup complete"
477
+ echo " New list: $NEW_LIST"
478
+ echo " Review new list before deleting old list"
479
+
480
+ rm clean.csv
481
+ else
482
+ echo "Cleanup cancelled"
483
+ fi
484
+ ```
485
+
486
+ ## List Metrics & Analysis
487
+
488
+ ### View List Statistics
489
+
490
+ ```bash
491
+ $ cakemail lists get 123 -f json | jq '{
492
+ name: .name,
493
+ total: .contacts_count,
494
+ active: .active_contacts,
495
+ unsubscribed: .unsubscribed,
496
+ bounced: .bounced,
497
+ health: (.active_contacts / .contacts_count * 100 | round)
498
+ }'
499
+ ```
500
+
501
+ **Output:**
502
+ ```json
503
+ {
504
+ "name": "Newsletter Subscribers",
505
+ "total": 1247,
506
+ "active": 1189,
507
+ "unsubscribed": 45,
508
+ "bounced": 13,
509
+ "health": 95
510
+ }
511
+ ```
512
+
513
+ ### Compare List Performance
514
+
515
+ ```bash
516
+ #!/bin/bash
517
+ # compare-lists.sh
518
+
519
+ echo "=== List Comparison ==="
520
+ echo ""
521
+
522
+ # Get all lists
523
+ cakemail lists list -f json | jq -r '.data[] |
524
+ "List: \(.name)\n ID: \(.id)\n Contacts: \(.contacts_count)\n Active: \(.active_contacts)\n Growth: +\(.contacts_count - .active_contacts) inactive\n"'
525
+ ```
526
+
527
+ ### Track List Growth
528
+
529
+ ```bash
530
+ #!/bin/bash
531
+ # track-growth.sh
532
+
533
+ LIST_ID=$1
534
+ LOG_FILE="list-growth-$LIST_ID.log"
535
+
536
+ # Get current count
537
+ CURRENT=$(cakemail lists get $LIST_ID -f json | jq -r '.contacts_count')
538
+ DATE=$(date +%Y-%m-%d)
539
+
540
+ # Log to file
541
+ echo "$DATE,$CURRENT" >> $LOG_FILE
542
+
543
+ # Show recent growth
544
+ echo "=== List Growth: $LIST_ID ==="
545
+ echo ""
546
+ echo "Date | Count | Change"
547
+ echo "-----------|-------|-------"
548
+
549
+ # Calculate changes
550
+ tail -30 $LOG_FILE | awk -F',' '
551
+ NR > 1 {
552
+ change = $2 - prev
553
+ printf "%s | %5d | %+6d\n", $1, $2, change
554
+ }
555
+ {prev = $2}
556
+ '
557
+
558
+ echo ""
559
+ echo "Run this script daily via cron to track growth"
560
+ ```
561
+
562
+ ## List Best Practices
563
+
564
+ ### 1. Keep Lists Focused
565
+
566
+ ```bash
567
+ # Good: Focused lists
568
+ Newsletter Subscribers # General updates
569
+ Product A Users # Specific product
570
+ VIP Customers # High-value segment
571
+
572
+ # Avoid: Catch-all lists
573
+ All Contacts # Too broad
574
+ Everyone # No segmentation
575
+ Main List # Unclear purpose
576
+ ```
577
+
578
+ ### 2. Name Lists Clearly
579
+
580
+ ```bash
581
+ # Good naming
582
+ $ cakemail lists create -n "Newsletter - Weekly Tech Tips" -l "en"
583
+ $ cakemail lists create -n "Product Updates - Enterprise" -l "en"
584
+ $ cakemail lists create -n "Event Invites - NYC Region" -l "en"
585
+
586
+ # Avoid vague names
587
+ $ cakemail lists create -n "List 1" -l "en" # ❌
588
+ $ cakemail lists create -n "Emails" -l "en" # ❌
589
+ $ cakemail lists create -n "Test" -l "en" # ❌
590
+ ```
591
+
592
+ ### 3. Regular List Maintenance
593
+
594
+ ```bash
595
+ #!/bin/bash
596
+ # monthly-maintenance.sh
597
+
598
+ echo "=== Monthly List Maintenance ==="
599
+ echo ""
600
+
601
+ # Get all lists
602
+ LISTS=$(cakemail lists list -f json | jq -r '.data[].id')
603
+
604
+ for LIST_ID in $LISTS; do
605
+ echo "Checking list $LIST_ID..."
606
+
607
+ # Get stats
608
+ LIST=$(cakemail lists get $LIST_ID -f json)
609
+ BOUNCED=$(echo "$LIST" | jq -r '.bounced')
610
+
611
+ # Alert if high bounce rate
612
+ if [ $BOUNCED -gt 100 ]; then
613
+ echo " ⚠️ High bounce count: $BOUNCED"
614
+ echo " Consider list cleanup"
615
+ fi
616
+ done
617
+
618
+ echo ""
619
+ echo "Maintenance check complete"
620
+ ```
621
+
622
+ ### 4. Document List Purpose
623
+
624
+ ```bash
625
+ # Create with descriptive description
626
+ $ cakemail lists create \
627
+ -n "Q1 Webinar Attendees" \
628
+ -l "en" \
629
+ -d "Contacts who attended any Q1 2024 webinar. Used for post-event nurture campaigns and future event invites."
630
+ ```
631
+
632
+ ### 5. Archive Inactive Lists
633
+
634
+ ```bash
635
+ #!/bin/bash
636
+ # archive-inactive-lists.sh
637
+
638
+ echo "=== Archiving Inactive Lists ==="
639
+ echo ""
640
+
641
+ CUTOFF_DATE=$(date -d "90 days ago" +%Y-%m-%d)
642
+
643
+ # Find lists not used recently
644
+ LISTS=$(cakemail lists list -f json | jq -r '.data[].id')
645
+
646
+ for LIST_ID in $LISTS; do
647
+ # Get latest campaign using this list
648
+ LATEST=$(cakemail campaigns list \
649
+ --filter "list_id==$LIST_ID" \
650
+ --sort "-delivered_at" \
651
+ --limit 1 \
652
+ -f json | jq -r '.data[0].delivered_at // "null"')
653
+
654
+ if [ "$LATEST" == "null" ] || [ "$LATEST" < "$CUTOFF_DATE" ]; then
655
+ NAME=$(cakemail lists get $LIST_ID -f json | jq -r '.name')
656
+ echo "⚠️ Inactive list: $NAME (ID: $LIST_ID)"
657
+ echo " Last used: ${LATEST:-Never}"
658
+
659
+ read -p " Archive this list? (yes/no): " ARCHIVE
660
+
661
+ if [ "$ARCHIVE" == "yes" ]; then
662
+ # Rename to indicate archived
663
+ cakemail lists update $LIST_ID -n "[ARCHIVED] $NAME"
664
+ echo " ✓ List archived"
665
+ fi
666
+ fi
667
+ done
668
+ ```
669
+
670
+ ## List Compliance
671
+
672
+ ### GDPR Considerations
673
+
674
+ ```bash
675
+ # Create consent-tracking attributes
676
+ $ cakemail attributes create 123 -n "consent_date" -t "date"
677
+ $ cakemail attributes create 123 -n "consent_method" -t "text"
678
+ $ cakemail attributes create 123 -n "consent_ip" -t "text"
679
+
680
+ # Add contact with consent tracking
681
+ $ cakemail contacts add 123 \
682
+ -e "user@example.com" \
683
+ -d '{
684
+ "consent_date": "2024-03-15",
685
+ "consent_method": "website_signup",
686
+ "consent_ip": "192.168.1.1"
687
+ }'
688
+ ```
689
+
690
+ ### CAN-SPAM Compliance
691
+
692
+ ```bash
693
+ # Every list must have:
694
+ # 1. Clear unsubscribe mechanism (automatic in Cakemail)
695
+ # 2. Physical address in footer
696
+ # 3. Honest subject lines
697
+ # 4. No deceptive headers
698
+
699
+ # Verify sender address configured
700
+ $ cakemail senders list -f json | jq '.data[] | {email, confirmed, address}'
701
+ ```
702
+
703
+ ### CASL Compliance (Canada)
704
+
705
+ ```bash
706
+ # Canadian Anti-Spam Law requirements
707
+ $ cakemail attributes create 123 -n "casl_consent" -t "boolean"
708
+ $ cakemail attributes create 123 -n "casl_consent_date" -t "date"
709
+ $ cakemail attributes create 123 -n "relationship_type" -t "text"
710
+
711
+ # Track implied vs express consent
712
+ $ cakemail contacts add 123 \
713
+ -e "canadian@example.com" \
714
+ -d '{
715
+ "casl_consent": true,
716
+ "casl_consent_date": "2024-03-15",
717
+ "relationship_type": "express"
718
+ }'
719
+ ```
720
+
721
+ ## Troubleshooting
722
+
723
+ ### Cannot Delete List
724
+
725
+ **Error:** "List has active campaigns"
726
+
727
+ **Solution:**
728
+ ```bash
729
+ # Find campaigns using list
730
+ $ cakemail campaigns list --filter "list_id==123" -f json
731
+
732
+ # Cancel or complete campaigns
733
+ $ cakemail campaigns cancel 790
734
+
735
+ # Or update campaigns to use different list
736
+ $ cakemail campaigns update 790 --list-id 124
737
+
738
+ # Then delete list
739
+ $ cakemail lists delete 123 --force
740
+ ```
741
+
742
+ ### List Growth Stagnant
743
+
744
+ **Problem:** List not growing
745
+
746
+ **Solutions:**
747
+ ```bash
748
+ # Check recent imports
749
+ $ cakemail contacts import-list 123
750
+
751
+ # Verify signup forms active
752
+ # Check website forms, landing pages
753
+
754
+ # Review unsubscribe rate
755
+ $ cakemail lists get 123 -f json | jq '{unsub: .unsubscribed, total: .contacts_count}'
756
+
757
+ # If high unsubscribe rate (> 2%):
758
+ # - Review content relevance
759
+ # - Check send frequency
760
+ # - Improve targeting
761
+ ```
762
+
763
+ ### High Bounce Rate
764
+
765
+ **Problem:** Many bounced contacts
766
+
767
+ **Solutions:**
768
+ ```bash
769
+ # Check bounce count
770
+ $ cakemail lists get 123 -f json | jq '.bounced'
771
+
772
+ # If > 5% of list:
773
+ # 1. Verify email collection process
774
+ # 2. Use double opt-in
775
+ # 3. Clean list regularly
776
+ # 4. Check for spam traps
777
+
778
+ # Remove hard bounces
779
+ # (Use list cleanup workflow above)
780
+ ```
781
+
782
+ ### Duplicate Contacts Across Lists
783
+
784
+ **Problem:** Same contact in multiple lists
785
+
786
+ **Not an error** - this is intentional:
787
+ ```bash
788
+ # Contacts can be in multiple lists
789
+ $ cakemail contacts add 123 -e "user@example.com" # Newsletter
790
+ $ cakemail contacts add 124 -e "user@example.com" # Product Updates
791
+
792
+ # Different lists = different campaign types
793
+ # Contact can unsubscribe from one but stay on others
794
+ ```
795
+
796
+ **If duplicate is unintended:**
797
+ ```bash
798
+ # Remove from one list
799
+ $ cakemail contacts delete 124 <contact-id> --force
800
+ ```
801
+
802
+ ### List Language Setting Issues
803
+
804
+ **Problem:** List created with wrong language
805
+
806
+ **Solution:**
807
+ ```bash
808
+ # Cannot change list language after creation
809
+ # Must create new list and migrate:
810
+
811
+ # 1. Create new list with correct language
812
+ $ cakemail lists create -n "Newsletter - Français" -l "fr"
813
+
814
+ # 2. Export contacts from old list
815
+ $ cakemail contacts export 123
816
+
817
+ # 3. Import to new list
818
+ # (See List Consolidation workflow)
819
+
820
+ # 4. Delete old list
821
+ $ cakemail lists delete 123 --force
822
+ ```
823
+
824
+ ## Best Practices Summary
825
+
826
+ 1. **Focus each list** - One clear purpose per list
827
+ 2. **Name descriptively** - Clear, self-explanatory names
828
+ 3. **Add descriptions** - Document list purpose and use
829
+ 4. **Monitor health** - Track active vs inactive contacts
830
+ 5. **Clean regularly** - Remove bounces and unsubscribes
831
+ 6. **Track consent** - Document subscription source and date
832
+ 7. **Segment appropriately** - Use lists for major segments, segments for minor
833
+ 8. **Archive inactive** - Don't delete, archive old lists
834
+ 9. **Document strategy** - Keep list strategy documentation
835
+ 10. **Review quarterly** - Assess list performance and cleanup
836
+