Skip to main content

max / makenotwork

7.8 KB · 271 lines History Blame Raw
1 //! Purchase, subscription, and Fan+ programme email templates.
2
3 use crate::email::EmailClient;
4 use crate::error::Result;
5
6 impl EmailClient {
7 /// Send a purchase confirmation email
8 pub async fn send_purchase_confirmation(
9 &self,
10 to_email: &str,
11 to_name: Option<&str>,
12 item_title: &str,
13 price: &str,
14 ) -> Result<()> {
15 let subject = "Your purchase is confirmed";
16 let body = format!(
17 r"Hi{name},
18
19 Your purchase of {item} ({price}) is confirmed.
20
21 You can access your purchase from your library at any time.
22
23 - Makenotwork",
24 name = crate::email::greeting(to_name),
25 item = item_title,
26 price = price
27 );
28
29 self.transport.send_email(to_email, subject, &body).await
30 }
31
32 /// Send a guest purchase confirmation email with download and claim links.
33 pub async fn send_guest_purchase_confirmation(
34 &self,
35 to_email: &str,
36 item_title: &str,
37 price: &str,
38 download_url: &str,
39 claim_url: &str,
40 ) -> Result<()> {
41 let subject = "Your purchase is confirmed";
42 let body = format!(
43 r"Hi,
44
45 Your purchase of {item_title} ({price}) is confirmed.
46
47 Download your purchase:
48 {download_url}
49
50 This link works without an account. You can download at any time.
51
52 Want to keep all your purchases in one place? Create a Makenot.work account with this email address and your purchase will appear in your library automatically. Or use this link to claim it to an existing account:
53 {claim_url}
54
55 - Makenotwork",
56 );
57
58 self.transport.send_email(to_email, subject, &body).await
59 }
60
61 /// Send a subscription started email
62 pub async fn send_subscription_started(
63 &self,
64 to_email: &str,
65 to_name: Option<&str>,
66 tier_name: &str,
67 project_title: &str,
68 price: &str,
69 ) -> Result<()> {
70 let subject = &format!("You're subscribed to {project_title}");
71 let body = format!(
72 r"Hi{name},
73
74 You're now subscribed to {project} ({tier} - {price}/mo).
75
76 You have access to all content included in this tier. Your subscription will renew automatically each month.
77
78 - Makenotwork",
79 name = crate::email::greeting(to_name),
80 project = project_title,
81 tier = tier_name,
82 price = price
83 );
84
85 self.transport.send_email(to_email, subject, &body).await
86 }
87
88 /// Send a subscription cancelled email
89 pub async fn send_subscription_cancelled(
90 &self,
91 to_email: &str,
92 to_name: Option<&str>,
93 tier_name: &str,
94 project_title: &str,
95 ) -> Result<()> {
96 let subject = "Your subscription has been cancelled";
97 let body = format!(
98 r"Hi{name},
99
100 Your subscription to {project} ({tier}) has been cancelled.
101
102 You will retain access until the end of your current billing period.
103
104 - Makenotwork",
105 name = crate::email::greeting(to_name),
106 project = project_title,
107 tier = tier_name
108 );
109
110 self.transport.send_email(to_email, subject, &body).await
111 }
112
113 /// Send a subscription renewed email
114 pub async fn send_subscription_renewed(
115 &self,
116 to_email: &str,
117 to_name: Option<&str>,
118 tier_name: &str,
119 price: &str,
120 ) -> Result<()> {
121 let subject = "Your subscription has been renewed";
122 let body = format!(
123 r"Hi{name},
124
125 Your subscription ({tier} - {price}/mo) has been renewed for another month.
126
127 - Makenotwork",
128 name = crate::email::greeting(to_name),
129 tier = tier_name,
130 price = price
131 );
132
133 self.transport.send_email(to_email, subject, &body).await
134 }
135
136 /// Send a Fan+ welcome email after subscription starts.
137 pub async fn send_fan_plus_welcome(&self, to_email: &str, to_name: Option<&str>) -> Result<()> {
138 let subject = "Welcome to Fan+";
139 let body = format!(
140 r"Hi{name},
141
142 You're now a Fan+ member.
143
144 Each month you'll receive a $5 credit code you can use toward any purchase on the platform. Your first credit will arrive with your next billing cycle.
145
146 Thank you for supporting Makenotwork.
147
148 - Makenotwork",
149 name = crate::email::greeting(to_name),
150 );
151
152 self.transport.send_email(to_email, subject, &body).await
153 }
154
155 /// Send a Fan+ monthly credit code email.
156 pub async fn send_fan_plus_credit(
157 &self,
158 to_email: &str,
159 to_name: Option<&str>,
160 code: &str,
161 expiry: Option<&chrono::DateTime<chrono::Utc>>,
162 ) -> Result<()> {
163 let subject = "Your Fan+ monthly credit";
164 let expiry_line = expiry
165 .map(|d| format!("\n\nThis code expires on {}.", d.format("%B %-d, %Y")))
166 .unwrap_or_default();
167 let body = format!(
168 r"Hi{name},
169
170 Your $5 Fan+ credit for this month is ready.
171
172 Code: {code}
173
174 Enter this code at checkout to apply it toward any purchase on the platform.{expiry}
175
176 - Makenotwork",
177 name = crate::email::greeting(to_name),
178 code = code,
179 expiry = expiry_line,
180 );
181
182 self.transport.send_email(to_email, subject, &body).await
183 }
184
185 /// Notify a creator that their backgrounded content export is ready, with a
186 /// time-limited download link. The export ZIP is built off the request path,
187 /// so the link arrives by email rather than inline in the dashboard.
188 pub async fn send_content_export_ready(
189 &self,
190 to_email: &str,
191 to_name: Option<&str>,
192 download_url: &str,
193 ) -> Result<()> {
194 let subject = "Your content export is ready";
195 let body = format!(
196 r"Hi{name},
197
198 Your content export is ready to download:
199
200 {url}
201
202 This link expires in one hour. If it expires before you download, start a new export from your dashboard.
203
204 - Makenotwork",
205 name = crate::email::greeting(to_name),
206 url = download_url,
207 );
208
209 self.transport.send_email(to_email, subject, &body).await
210 }
211
212 /// Notify a creator that their content export could not be completed, so a
213 /// silently-failed background job doesn't leave them waiting indefinitely.
214 pub async fn send_content_export_failed(
215 &self,
216 to_email: &str,
217 to_name: Option<&str>,
218 reason: Option<&str>,
219 ) -> Result<()> {
220 let subject = "Your content export could not be completed";
221 let reason_line = reason.map(|r| format!("\n\n{r}")).unwrap_or_default();
222 let body = format!(
223 r"Hi{name},
224
225 We were unable to finish preparing your content export. No changes were made to your content.{reason}
226
227 Please try again from your dashboard; if it keeps failing, contact info@makenot.work.
228
229 - Makenotwork",
230 name = crate::email::greeting(to_name),
231 reason = reason_line,
232 );
233
234 self.transport.send_email(to_email, subject, &body).await
235 }
236
237 /// Send a Fan+ cancellation email.
238 pub async fn send_fan_plus_cancelled(
239 &self,
240 to_email: &str,
241 to_name: Option<&str>,
242 period_end: Option<&chrono::DateTime<chrono::Utc>>,
243 ) -> Result<()> {
244 let subject = "Your Fan+ membership has been cancelled";
245 let access_line = period_end.map_or_else(
246 || "Your Fan+ benefits have ended.".to_string(),
247 |d| {
248 format!(
249 "You will retain your Fan+ benefits until {}.",
250 d.format("%B %-d, %Y")
251 )
252 },
253 );
254 let body = format!(
255 r"Hi{name},
256
257 Your Fan+ membership has been cancelled.
258
259 {access}
260
261 Any unused credit codes remain valid until their expiry date.
262
263 - Makenotwork",
264 name = crate::email::greeting(to_name),
265 access = access_line,
266 );
267
268 self.transport.send_email(to_email, subject, &body).await
269 }
270 }
271