Author: Manos Pitsidianakis [manos@pitsidianak.is]
Hash: 1eb8d7ad221af3738636d5b3ba90e693fe02a272
Timestamp: Mon, 30 Oct 2023 16:36:24 +0000 (10 months ago)

+147 -32 +/-5 browse
cli: add command to send subscription confirmation manually
cli: add command to send subscription confirmation manually

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
1diff --git a/cli/src/args.rs b/cli/src/args.rs
2index 2184b1f..e1da086 100644
3--- a/cli/src/args.rs
4+++ b/cli/src/args.rs
5 @@ -356,6 +356,14 @@ pub enum ListCommand {
6 AcceptSubscriptionRequest {
7 /// The primary key of the request.
8 pk: i64,
9+ /// Do not send confirmation e-mail.
10+ #[arg(long, default_value = "false")]
11+ do_not_send_confirmation: bool,
12+ },
13+ /// Send subscription confirmation manually.
14+ SendConfirmationForSubscription {
15+ /// The primary key of the subscription.
16+ pk: i64,
17 },
18 /// Add a new post policy.
19 AddPostPolicy {
20 diff --git a/cli/src/main.rs b/cli/src/main.rs
21index 62aa476..6e10a05 100644
22--- a/cli/src/main.rs
23+++ b/cli/src/main.rs
24 @@ -493,15 +493,76 @@ fn run_app(opt: Opt) -> Result<()> {
25 }
26 }
27 }
28- AcceptSubscriptionRequest { pk } => match db.accept_candidate_subscription(pk) {
29+ AcceptSubscriptionRequest {
30+ pk,
31+ do_not_send_confirmation,
32+ } => match db.accept_candidate_subscription(pk) {
33 Ok(subscription) => {
34 println!("Added: {subscription:#?}");
35+ if !do_not_send_confirmation {
36+ if let Err(err) = db
37+ .list(subscription.list)
38+ .and_then(|v| match v {
39+ Some(v) => Ok(v),
40+ None => Err(format!(
41+ "No list with id or pk {} was found",
42+ subscription.list
43+ )
44+ .into()),
45+ })
46+ .and_then(|list| {
47+ db.send_subscription_confirmation(
48+ &list,
49+ &subscription.address(),
50+ )
51+ })
52+ {
53+ eprintln!("Could not send subscription confirmation!");
54+ return Err(err);
55+ }
56+ println!("Sent confirmation e-mail to {}", subscription.address());
57+ } else {
58+ println!(
59+ "Did not sent confirmation e-mail to {}. You can do it manually \
60+ with the appropriate command.",
61+ subscription.address()
62+ );
63+ }
64 }
65 Err(err) => {
66 eprintln!("Could not accept subscription request!");
67 return Err(err);
68 }
69 },
70+ SendConfirmationForSubscription { pk } => {
71+ let req = match db.candidate_subscription(pk) {
72+ Ok(req) => req,
73+ Err(err) => {
74+ eprintln!("Could not find subscription request by that pk!");
75+
76+ return Err(err);
77+ }
78+ };
79+ log::info!("Found {:#?}", req);
80+ if req.accepted.is_none() {
81+ return Err("Request has not been accepted!".into());
82+ }
83+ if let Err(err) = db
84+ .list(req.list)
85+ .and_then(|v| match v {
86+ Some(v) => Ok(v),
87+ None => {
88+ Err(format!("No list with id or pk {} was found", req.list).into())
89+ }
90+ })
91+ .and_then(|list| db.send_subscription_confirmation(&list, &req.address()))
92+ {
93+ eprintln!("Could not send subscription request confirmation!");
94+ return Err(err);
95+ }
96+
97+ println!("Sent confirmation e-mail to {}", req.address());
98+ }
99 }
100 }
101 CreateList {
102 diff --git a/core/src/models.rs b/core/src/models.rs
103index 5348eec..cbc76da 100644
104--- a/core/src/models.rs
105+++ b/core/src/models.rs
106 @@ -728,6 +728,13 @@ pub struct ListCandidateSubscription {
107 pub accepted: Option<i64>,
108 }
109
110+ impl ListCandidateSubscription {
111+ /// Subscription request address as a [`melib::Address`]
112+ pub fn address(&self) -> Address {
113+ Address::new(self.name.clone(), self.address.clone())
114+ }
115+ }
116+
117 impl std::fmt::Display for ListCandidateSubscription {
118 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
119 write!(
120 diff --git a/core/src/posts.rs b/core/src/posts.rs
121index 995929d..b3bef9a 100644
122--- a/core/src/posts.rs
123+++ b/core/src/posts.rs
124 @@ -491,23 +491,7 @@ impl Connection {
125 list_owners.iter().map(|owner| Cow::Owned(owner.address())),
126 )?;
127 } else {
128- log::trace!(
129- "Added subscription to list {list:?} for address {f:?}, sending \
130- confirmation."
131- );
132- self.send_reply_with_list_template(
133- TemplateRenderContext {
134- template: Template::SUBSCRIPTION_CONFIRMATION,
135- default_fn: Some(Template::default_subscription_confirmation),
136- list,
137- context: minijinja::context! {
138- list => &list,
139- },
140- queue: Queue::Out,
141- comment: Template::SUBSCRIPTION_CONFIRMATION.into(),
142- },
143- std::iter::once(Cow::Borrowed(f)),
144- )?;
145+ self.send_subscription_confirmation(list, f)?;
146 }
147 }
148 }
149 @@ -554,19 +538,7 @@ impl Connection {
150 list_owners.iter().map(|owner| Cow::Owned(owner.address())),
151 )?;
152 } else {
153- self.send_reply_with_list_template(
154- TemplateRenderContext {
155- template: Template::UNSUBSCRIPTION_CONFIRMATION,
156- default_fn: Some(Template::default_unsubscription_confirmation),
157- list,
158- context: minijinja::context! {
159- list => &list,
160- },
161- queue: Queue::Out,
162- comment: Template::UNSUBSCRIPTION_CONFIRMATION.into(),
163- },
164- std::iter::once(Cow::Borrowed(f)),
165- )?;
166+ self.send_unsubscription_confirmation(list, f)?;
167 }
168 }
169 }
170 @@ -765,6 +737,54 @@ impl Connection {
171 }
172 Ok(())
173 }
174+
175+ /// Send subscription confirmation.
176+ pub fn send_subscription_confirmation(
177+ &self,
178+ list: &DbVal<MailingList>,
179+ address: &melib::Address,
180+ ) -> Result<()> {
181+ log::trace!(
182+ "Added subscription to list {list:?} for address {address:?}, sending confirmation."
183+ );
184+ self.send_reply_with_list_template(
185+ TemplateRenderContext {
186+ template: Template::SUBSCRIPTION_CONFIRMATION,
187+ default_fn: Some(Template::default_subscription_confirmation),
188+ list,
189+ context: minijinja::context! {
190+ list => &list,
191+ },
192+ queue: Queue::Out,
193+ comment: Template::SUBSCRIPTION_CONFIRMATION.into(),
194+ },
195+ std::iter::once(Cow::Borrowed(address)),
196+ )
197+ }
198+
199+ /// Send unsubscription confirmation.
200+ pub fn send_unsubscription_confirmation(
201+ &self,
202+ list: &DbVal<MailingList>,
203+ address: &melib::Address,
204+ ) -> Result<()> {
205+ log::trace!(
206+ "Removed subscription to list {list:?} for address {address:?}, sending confirmation."
207+ );
208+ self.send_reply_with_list_template(
209+ TemplateRenderContext {
210+ template: Template::UNSUBSCRIPTION_CONFIRMATION,
211+ default_fn: Some(Template::default_unsubscription_confirmation),
212+ list,
213+ context: minijinja::context! {
214+ list => &list,
215+ },
216+ queue: Queue::Out,
217+ comment: Template::UNSUBSCRIPTION_CONFIRMATION.into(),
218+ },
219+ std::iter::once(Cow::Borrowed(address)),
220+ )
221+ }
222 }
223
224 /// Helper type for [`Connection::send_reply_with_list_template`].
225 diff --git a/docs/mpot.1 b/docs/mpot.1
226index ae10fd7..d82f5a8 100644
227--- a/docs/mpot.1
228+++ b/docs/mpot.1
229 @@ -346,13 +346,32 @@ Is subscription enabled.
230
231 .br
232
233- mpot list accept\-subscription\-request \fIPK\fR
234+ mpot list accept\-subscription\-request [\-\-do\-not\-send\-confirmation \fIDO_NOT_SEND_CONFIRMATION\fR] \fIPK\fR
235 .br
236
237 Accept a subscription request by its primary key.
238 .TP
239 \fIPK\fR
240 The primary key of the request.
241+ .TP
242+ \-\-do\-not\-send\-confirmation
243+ Do not send confirmation e\-mail.
244+ .ie \n(.g .ds Aq \(aq
245+ .el .ds Aq '
246+ .\fB
247+ .SS mpot list send-confirmation-for-subscription
248+ .\fR
249+ .br
250+
251+ .br
252+
253+ mpot list send\-confirmation\-for\-subscription \fIPK\fR
254+ .br
255+
256+ Send subscription confirmation manually.
257+ .TP
258+ \fIPK\fR
259+ The primary key of the subscription.
260 .ie \n(.g .ds Aq \(aq
261 .el .ds Aq '
262 .\fB