1
/*
2
 * This file is part of mailpot
3
 *
4
 * Copyright 2020 - Manos Pitsidianakis
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as
8
 * published by the Free Software Foundation, either version 3 of the
9
 * License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License
17
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18
 */
19

            
20
//! Template database model: [`Template`].
21

            
22
use super::*;
23

            
24
/// A named template.
25
4
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
26
pub struct Template {
27
    /// Database primary key.
28
2
    pub pk: i64,
29
    /// Name.
30
2
    pub name: String,
31
    /// Associated list foreign key, optional.
32
2
    pub list: Option<i64>,
33
    /// Subject template.
34
2
    pub subject: Option<String>,
35
    /// Extra headers template.
36
    pub headers_json: Option<serde_json::Value>,
37
    /// Body template.
38
2
    pub body: String,
39
}
40

            
41
impl std::fmt::Display for Template {
42
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
43
        write!(fmt, "{:?}", self)
44
    }
45
}
46

            
47
impl Template {
48
    /// Template name for generic list help e-mail.
49
    pub const GENERIC_HELP: &str = "generic-help";
50
    /// Template name for generic failure e-mail.
51
    pub const GENERIC_FAILURE: &str = "generic-failure";
52
    /// Template name for generic success e-mail.
53
    pub const GENERIC_SUCCESS: &str = "generic-success";
54
    /// Template name for subscription confirmation e-mail.
55
    pub const SUBSCRIPTION_CONFIRMATION: &str = "subscription-confirmation";
56
    /// Template name for unsubscription confirmation e-mail.
57
    pub const UNSUBSCRIPTION_CONFIRMATION: &str = "unsubscription-confirmation";
58
    /// Template name for subscription request notice e-mail (for list owners).
59
    pub const SUBSCRIPTION_REQUEST_NOTICE_OWNER: &str = "subscription-notice-owner";
60
    /// Template name for subscription request acceptance e-mail (for the
61
    /// candidates).
62
    pub const SUBSCRIPTION_REQUEST_CANDIDATE_ACCEPT: &str = "subscription-notice-candidate-accept";
63
    /// Template name for admin notices.
64
    pub const ADMIN_NOTICE: &str = "admin-notice";
65

            
66
    /// Render a message body from a saved named template.
67
13
    pub fn render(&self, context: minijinja::value::Value) -> Result<melib::Draft> {
68
        use melib::{Draft, HeaderName};
69

            
70
13
        let env = minijinja::Environment::new();
71
13
        let mut draft: Draft = Draft {
72
13
            body: env.render_named_str("body", &self.body, &context)?,
73
13
            ..Draft::default()
74
13
        };
75
13
        if let Some(ref subject) = self.subject {
76
13
            draft.headers.insert(
77
13
                HeaderName::new_unchecked("Subject"),
78
13
                env.render_named_str("subject", subject, &context)?,
79
13
            );
80
        }
81

            
82
13
        Ok(draft)
83
13
    }
84

            
85
    /// Template name for generic failure e-mail.
86
3
    pub fn default_generic_failure() -> Self {
87
3
        Self {
88
            pk: -1,
89
3
            name: Self::GENERIC_FAILURE.to_string(),
90
3
            list: None,
91
3
            subject: Some(
92
3
                "{{ subject if subject else \"Your e-mail was not processed successfully.\" }}"
93
                    .to_string(),
94
            ),
95
3
            headers_json: None,
96
3
            body: "{{ details|safe if details else \"The list owners and administrators have been \
97
                   notified.\" }}"
98
                .to_string(),
99
        }
100
3
    }
101

            
102
    /// Create a plain template for generic success e-mails.
103
    pub fn default_generic_success() -> Self {
104
        Self {
105
            pk: -1,
106
            name: Self::GENERIC_SUCCESS.to_string(),
107
            list: None,
108
            subject: Some(
109
                "{{ subject if subject else \"Your e-mail was processed successfully.\" }}"
110
                    .to_string(),
111
            ),
112
            headers_json: None,
113
            body: "{{ details|safe if details else \"\" }}".to_string(),
114
        }
115
    }
116

            
117
    /// Create a plain template for subscription confirmation.
118
7
    pub fn default_subscription_confirmation() -> Self {
119
7
        Self {
120
            pk: -1,
121
7
            name: Self::SUBSCRIPTION_CONFIRMATION.to_string(),
122
7
            list: None,
123
7
            subject: Some(
124
7
                "{% if list and (list.id or list.name) %}{% if list.id %}[{{ list.id }}] {% endif \
125
                 %}You have successfully subscribed to {{ list.name if list.name else list.id \
126
                 }}{% else %}You have successfully subscribed to this list{% endif %}."
127
                    .to_string(),
128
            ),
129
7
            headers_json: None,
130
7
            body: "{{ details|safe if details else \"\" }}".to_string(),
131
        }
132
7
    }
133

            
134
    /// Create a plain template for unsubscription confirmations.
135
1
    pub fn default_unsubscription_confirmation() -> Self {
136
1
        Self {
137
            pk: -1,
138
1
            name: Self::UNSUBSCRIPTION_CONFIRMATION.to_string(),
139
1
            list: None,
140
1
            subject: Some(
141
1
                "{% if list and (list.id or list.name) %}{% if list.id %}[{{ list.id }}] {% endif \
142
                 %}You have successfully unsubscribed from {{ list.name if list.name else list.id \
143
                 }}{% else %}You have successfully unsubscribed from this list{% endif %}."
144
                    .to_string(),
145
            ),
146
1
            headers_json: None,
147
1
            body: "{{ details|safe if details else \"\" }}".to_string(),
148
        }
149
1
    }
150

            
151
    /// Create a plain template for admin notices.
152
    pub fn default_admin_notice() -> Self {
153
        Self {
154
            pk: -1,
155
            name: Self::ADMIN_NOTICE.to_string(),
156
            list: None,
157
            subject: Some(
158
                "{% if list %}An error occured with list {{ list.id }}{% else %}An error \
159
                 occured{% endif %}"
160
                    .to_string(),
161
            ),
162
            headers_json: None,
163
            body: "{{ details|safe if details else \"\" }}".to_string(),
164
        }
165
    }
166

            
167
    /// Create a plain template for subscription requests for list owners.
168
    pub fn default_subscription_request_owner() -> Self {
169
        Self {
170
            pk: -1,
171
            name: Self::SUBSCRIPTION_REQUEST_NOTICE_OWNER.to_string(),
172
            list: None,
173
            subject: Some("Subscription request for {{ list.id }} by {{ candidate }}".to_string()),
174
            headers_json: None,
175
            body: "Candidate primary key: {{ candidate.pk }}\n\n{{ details|safe if details else \
176
                   \"\" }}"
177
                .to_string(),
178
        }
179
    }
180

            
181
    /// Create a plain template for subscription requests for candidates.
182
    pub fn default_subscription_request_candidate_accept() -> Self {
183
        Self {
184
            pk: -1,
185
            name: Self::SUBSCRIPTION_REQUEST_CANDIDATE_ACCEPT.to_string(),
186
            list: None,
187
            subject: Some("Your subscription to {{ list.id }} is now active.".to_string()),
188
            headers_json: None,
189
            body: "{{ details|safe if details else \"\" }}".to_string(),
190
        }
191
    }
192

            
193
    /// Create a plain template for generic list help replies.
194
1
    pub fn default_generic_help() -> Self {
195
1
        Self {
196
            pk: -1,
197
1
            name: Self::GENERIC_HELP.to_string(),
198
1
            list: None,
199
1
            subject: Some("{{ subject if subject else \"Help for mailing list\" }}".to_string()),
200
1
            headers_json: None,
201
1
            body: "{{ details }}".to_string(),
202
        }
203
1
    }
204
}