From 6dcd0cadcca91c18d12d9674e6ec3ce60cb44d31 Mon Sep 17 00:00:00 2001 From: Jason Woofenden Date: Thu, 24 Dec 2015 22:16:26 -0500 Subject: [PATCH] add admin_email_templates --- admin_email_templates.html | 106 +++++++++++++++++++++++++ admin_email_templates.php | 186 ++++++++++++++++++++++++++++++++++++++++++++ admin_email_templates.sql | 12 +++ config.php | 15 ++++ inc/ckeditor | 2 +- inc/misc.php | 52 +++++++++++++ inc/wfpl | 2 +- 7 files changed, 373 insertions(+), 2 deletions(-) create mode 100644 admin_email_templates.html create mode 100644 admin_email_templates.php create mode 100644 admin_email_templates.sql diff --git a/admin_email_templates.html b/admin_email_templates.html new file mode 100644 index 0000000..a2a3e00 --- /dev/null +++ b/admin_email_templates.html @@ -0,0 +1,106 @@ + + + + + + <!--~$title show {~-->Email templates<!--~}~--> + + + + + + +

Edit email template "~title html~"

+ +

~description htmlbrtab~

+ +
+
Notes
+
This is here just for admins to save any kind of notes (for example clarifications on when/how this email template is used, or notes on what the template was like previously.)
+
+ +
"From:" email address (required)
+
When this email template is used, the email generated will be sent from this address.
+
To supply a name also, use this exact format: John Smith <john@example.com>
+
+ + +
"To:" email address (required)
+
When this email template is used, the email generated will sent to this address.
+
To supply a name also, use this exact format: John Smith <john@example.com>
+
+ + +
"Cc:" email address (optional)
+
If you enter an email address here, it will be added to the "Cc:" header, that is, it will get a copy of every email that uses this template. Note that the "Cc:" header is visible to all recipients, so this feature should probably only be used for testing.
+
To supply a name also, use this exact format: John Smith <john@example.com>
+
+ +
"Bcc:" email address (optional)
+
If you enter an email address here, it will be added to the "Bcc:" header, that is, it will get a copy of every email that uses this template. This email address will not be visible to recipients, and will not be included in replies.
+
To supply a name also, use this exact format: John Smith <john@example.com>
+
+ +
Template Variables
+
You can place variables into the Subject and Message Body fields. This can be used, for example, to insert the recipients username into the message. Below is a table showing the variables that are available for this particular email template: + + + + + + + + + + + + + + + +
VariableDescription
~~~~Puts a single ~~ in the email. You must do this if you want a ~~ in your email.
~~~0~~~~1~
+
+ +
Subject
+
This field uses template variables, see above.
+
+ +
Message Body
+
This field uses template variables, see above.
+
+ +
+
+ + +
+ +
+ +
 
+
Cancel
+ + + +

Email Templates

+ +

Click one to edit:

+ + + + + + + + + + + + +
Template TitleEmail Subject
~title html~(blank)~subject html~(blank)
+ + + + + + diff --git a/admin_email_templates.php b/admin_email_templates.php new file mode 100644 index 0000000..10ed922 --- /dev/null +++ b/admin_email_templates.php @@ -0,0 +1,186 @@ + [ +# 'title' => "Title shown in admin only", +# 'description' => "explain (for admins) what this template is for", +# 'variables' => [ +# ['name', "explan (for admins) what this variable is for"], +# ['verbing', "admins can put these variables into the template"] +# ], +# 'subject' => "email subject", +# 'content' => "Hi, ~name~ this is the email body, thanks for ~verbing~!", +# 'from_addr' => 'noreply@airservices.info', +# 'to_addr' => 'optional@to.address' # optional +# ] +# # , 'slug2' => ... +# ]; + +# To save results to a database, you'll need to create the email_templates table. +# The file admin_email_templates.sql should help with this +# +# if you rename any of the database fields, you'll need to update this: +define('ADMIN_EMAIL_TEMPLATES_DB_FIELDS', 'slug,notes,from_addr,to_addr,cc_addr,bcc_addr,subject,content'); + + +$GLOBALS['admin_email_templates_field_to_caption'] = array( + 'slug' => 'Slug', + 'notes' => 'Notes', + 'from_addr' => 'From Address', + 'to_addr' => 'To Address', + 'cc_addr' => 'Cc Address', + 'bcc_addr' => 'Bcc Address', + 'subject' => 'Subject', + 'content' => 'Content' +); + +function admin_email_templates_get_fields() { + $data = array(); + + # slug is cut in *_main() + $data['notes'] = format_unix(_REQUEST_cut('notes')); + $data['to_addr'] = format_email(trim(_REQUEST_cut('to_addr'))); + $data['from_addr'] = format_email(trim(_REQUEST_cut('from_addr'))); + $data['cc_addr'] = format_email(trim(_REQUEST_cut('cc_addr'))); + $data['bcc_addr'] = format_email(trim(_REQUEST_cut('bcc_addr'))); + $data['subject'] = format_oneline(trim(_REQUEST_cut('subject'))); + $data['content'] = format_unix(_REQUEST_cut('content')); + + return $data; +} + + +function admin_email_templates_main() { + session_auth_must('admin_email_templates'); + + $slug = _REQUEST_cut('slug'); + if ($slug && isset($GLOBALS['email_templates'][$slug])) { + return admin_email_templates_main_form($slug); + } + + # default action: + return admin_email_templates_main_listing(); +} + +function admin_email_templates_main_sort_title($a, $b) { + return strcasecmp($a['title'], $b['title']); +} +function admin_email_templates_main_sort_title_reverse($a, $b) { + return strcasecmp($b['title'], $a['title']); +} +function admin_email_templates_main_sort_subject($a, $b) { + return strcasecmp($a['subject'], $b['subject']); +} +function admin_email_templates_main_sort_subject_reverse($a, $b) { + return strcasecmp($b['subject'], $a['subject']); +} + +function admin_email_templates_main_listing() { + $data = array(); + $reverse = ''; + $sort = _REQUEST_cut('sort'); + if ($sort && substr($sort, 0, 1) === '-') { + $sort = substr($sort, 1); + $reverse = "_reverse"; + } else { + $data["sorting-by-$sort"] = '-'; + } + $legal_sorts = array('title', 'subject'); + if (!$sort || !in_array($sort, $legal_sorts)) { + $sort = 'title'; + } + + $data['rows'] = array(); + + $rows = db_get_assocs('email_templates', 'slug,from_addr,cc_addr,bcc_addr,subject'); + $by_slug = array(); + foreach ($rows as $row) { + $by_slug[$row['slug']] = $row; + } + foreach ($GLOBALS['email_templates'] as $slug => $row) { + $out = array('slug' => $slug); + # defaults from config + foreach($row as $k => $v) { + $out[$k] = $v; + } + # overwrite with db (if it's in the db) + if ($by_slug[$slug]) { + foreach($by_slug[$slug] as $k => $v) { + $out[$k] = $v; + } + } + $data['rows'][] = $out; + } + + usort($data['rows'], "admin_email_templates_main_sort_$sort$reverse"); + + tem_set('listings', $data); +} + +function admin_email_templates_main_form($slug) { + if (isset($_POST['subject'])) { + $data = admin_email_templates_get_fields(); + $data['slug'] = $slug; + + $all_good = true; + $email_fields = ['from', 'to', 'cc', 'bcc']; + foreach ($email_fields as &$field) { + $value = $data[$field . '_addr']; + if (strlen($value)) { + if (!email_header($value)) { + $pretty = ucfirst($field) . ':'; + message("ERROR: invalid value in \"$pretty\" field. Be very careful with formatting, and only put one address in this field."); + $all_good = false; + } + } + } unset($field); + + if (strlen($data['from_addr']) == 0) { + message("ERROR: the \"From:\" field is required."); + $all_good = false; + } + + if (strlen($data['to_addr']) == 0 && isset($GLOBALS['email_templates'][$slug]['to_addr'])) { + message("ERROR: the \"To:\" field is required for this template."); + $all_good = false; + } + if ($all_good) { + if (0 < db_count('email_templates', 'where slug=%"', $slug)) { + db_update_assoc('email_templates', $data, 'where slug=%"', $slug); + } else { + db_insert_assoc('email_templates', $data); + } + message('Email template updated.'); + if ($error !== true) { + return './admin_email_templates'; + } + } else { + $custom = $data; + } + } else { + $custom = db_get_assoc('email_templates', ADMIN_EMAIL_TEMPLATES_DB_FIELDS, 'where slug=%"', $slug); + } + + $out = array('slug' => $slug); + # defaults from globals + foreach($GLOBALS['email_templates'][$slug] as $k => $v) { + $out[$k] = $v; + } + # show 'to_addr' field if it's relevant + if (isset($out['to_addr'])) { + $out['want_to_addr'] = true; + } + # override with db values + if ($custom) { + foreach($custom as $k => $v) { + $out[$k] = $v; + } + } + tem_set('form', $out); +} diff --git a/admin_email_templates.sql b/admin_email_templates.sql new file mode 100644 index 0000000..dc11783 --- /dev/null +++ b/admin_email_templates.sql @@ -0,0 +1,12 @@ +drop table if exists email_templates; +create table email_templates ( + id int unique auto_increment, + slug varchar(200) binary not null default "", + notes text binary not null default "", + from_addr varchar(100) binary not null default "", + to_addr varchar(100) binary not null default "", + cc_addr varchar(100) binary not null default "", + bcc_addr varchar(100) binary not null default "", + subject varchar(200) binary not null default "", + content text binary not null default "" +) CHARSET=utf8; diff --git a/config.php b/config.php index 59b1c98..da021ef 100644 --- a/config.php +++ b/config.php @@ -35,3 +35,18 @@ if (isset($_SERVER['HTTP_X_UPGRADE_DB_NOW'])) { require_once(DOCROOT . 'inc/db_upgrade.php'); db_upgrade(); } + +$GLOBALS['email_templates'] = [ + 'backend_bug' => [ + 'title' => "Notification for site programmer(s)", + 'description' => "This email template is used if/when the back-end code of this site encounters an unusual/suspicious situation that it's not sure how to cope with.", + 'variables' => [ + ['message', "details about the unusual/suspicious situation"] + ], + 'subject' => "backend alert", + 'content' => "Hi developer,\n\nPlease investigate the following debugging message from the site:\n\n~message~" + 'from_addr' => 'noreply@example.com', + 'to_addr' => 'fixme@example.com' # not all templates need this field + ] + # ... +]; diff --git a/inc/ckeditor b/inc/ckeditor index a0df3d0..34d2dd8 160000 --- a/inc/ckeditor +++ b/inc/ckeditor @@ -1 +1 @@ -Subproject commit a0df3d0ab0c5252b5e2e0fd274705ede834c2276 +Subproject commit 34d2dd88753d873bd36d07d9917b326fa84ac464 diff --git a/inc/misc.php b/inc/misc.php index 429482d..aed971d 100644 --- a/inc/misc.php +++ b/inc/misc.php @@ -1,6 +1,58 @@ set('$render_timestamps'); } + +# helper for email_with_template() below +function get_email_template($slug, $template_variables, $to_addr) { + # defaults + $out = array( + 'subject' => $GLOBALS['email_templates'][$slug]['subject'], + 'content' => $GLOBALS['email_templates'][$slug]['content'], + 'from_addr' => $GLOBALS['email_templates'][$slug]['from_addr'], + 'to_addr' => '', + 'cc_addr' => '', + 'bcc_addr' => '' + ); + if (isset($GLOBALS['email_templates'][$slug]['to_addr'])) { + $out['to_addr'] = $GLOBALS['email_templates'][$slug]['to_addr']; + } else { + if ($to_addr == null) { + die("ERROR: email_with_template(\"$slug\") needs a to_addr (put in \$GLOBALS['email_templates']['$slug'] or pass as argument)"); + } + } + # override with DB (if it exists) + $row = db_get_assoc('email_templates', 'from_addr,to_addr,cc_addr,bcc_addr,subject,content', 'where slug=%"', $slug); + if ($row) { + foreach($row as $key => $value) { + $out[$key] = $value; + } + } + # argument wins no matter what + if ($to_addr !== null) { + $out['to_addr'] = $to_addr; + } + if (strpos($out['content'], '~') !== false) { + $tem = new tem(); + $tem->load_str($out['content']); + $tem->sets($template_variables); + $out['content'] = $tem->run(); + } + if (strpos($out['subject'], '~') !== false) { + $tem = new tem(); + $tem->load_str($out['subject']); + $tem->sets($template_variables); + $out['subject'] = $tem->run(); + } + return $out; +} + +# pass null as first arg if "to_addr" should come from the DB +function email_with_template($to_addr, $template_slug, $template_vars, $reply_to = '') { + $t = get_email_template($template_slug, $template_vars, $to_addr); + return email($t['from_addr'], $t['to_addr'], $t['subject'], $t['content'], $reply_to, $t['cc_addr'], $t['bcc_addr']); +} diff --git a/inc/wfpl b/inc/wfpl index 1cc2fd7..f58acc2 160000 --- a/inc/wfpl +++ b/inc/wfpl @@ -1 +1 @@ -Subproject commit 1cc2fd791d55bca1a63afbeb2628dd1a8bd2ba3f +Subproject commit f58acc2fd5e5fbfb4a01d6b66711b2f62bf77c4a -- 1.7.10.4