Fossil SCM

Add the /unsubscribe page.

drh 2018-06-22 03:17 UTC email-alerts
Commit f9116088243353b0f072c81061cb80a8cbd123a27633872d879d5ec7413bfac7
1 file changed +172 -11
+172 -11
--- src/email.c
+++ src/email.c
@@ -152,11 +152,11 @@
152152
void setup_email(void){
153153
static const char *const azSendMethods[] = {
154154
"off", "Disabled",
155155
"pipe", "Pipe to a command",
156156
"db", "Store in a database",
157
- "file", "Store in a directory"
157
+ "dir", "Store in a directory"
158158
};
159159
login_check_credentials();
160160
if( !g.perm.Setup ){
161161
login_needed(0);
162162
return;
@@ -571,13 +571,13 @@
571571
/*
572572
** Do error checking on a submitted subscription form. Return TRUE
573573
** if the submission is valid. Return false if any problems are seen.
574574
*/
575575
static int subscribe_error_check(
576
- int *peErr, /* Type of error */
577
- char **pzErr, /* Error message text */
578
- int needCaptcha /* True if captcha check needed */
576
+ int *peErr, /* Type of error */
577
+ char **pzErr, /* Error message text */
578
+ int needCaptcha /* True if captcha check needed */
579579
){
580580
const char *zEAddr;
581581
int i, j, n;
582582
char c;
583583
@@ -817,10 +817,35 @@
817817
}
818818
@ </form>
819819
fossil_free(zErr);
820820
style_footer();
821821
}
822
+
823
+/*
824
+** Either shutdown or completely delete a subscription entry given
825
+** by the hex value zName. Then paint a webpage that explains that
826
+** the entry has been removed.
827
+*/
828
+static void email_unsubscribe(const char *zName){
829
+ char *zEmail;
830
+ zEmail = db_text(0, "SELECT semail FROM subscriber"
831
+ " WHERE subscriberCode=hextoblob(%Q)", zName);
832
+ if( zEmail==0 ){
833
+ style_header("Unsubscribe Fail");
834
+ @ <p>Unable to locate a subscriber with the requested key</p>
835
+ }else{
836
+ db_multi_exec(
837
+ "DELETE FROM subscriber WHERE subscriberCode=hextoblob(%Q)",
838
+ zName
839
+ );
840
+ style_header("Unsubscribed");
841
+ @ <p>The "%h(zEmail)" email address has been delisted.
842
+ @ All traces of that email address have been removed</p>
843
+ }
844
+ style_footer();
845
+ return;
846
+}
822847
823848
/*
824849
** WEBPAGE: alerts
825850
**
826851
** Edit email alert and notification settings.
@@ -896,17 +921,11 @@
896921
if( !PB("dodelete") ){
897922
eErr = 9;
898923
zErr = mprintf("Select this checkbox and press \"Unsubscribe\" to"
899924
" unsubscribe");
900925
}else{
901
- db_multi_exec(
902
- "DELETE FROM subscriber WHERE subscriberCode=hextoblob(%Q)",
903
- zName
904
- );
905
- style_header("Email Subscription Deleted");
906
- @ <p>The email subscription has been deleted</p>
907
- style_footer();
926
+ email_unsubscribe(zName);
908927
return;
909928
}
910929
}
911930
db_prepare(&q,
912931
"SELECT"
@@ -999,10 +1018,152 @@
9991018
@ </form>
10001019
fossil_free(zErr);
10011020
db_finalize(&q);
10021021
style_footer();
10031022
}
1023
+
1024
+/* This is the message that gets sent to describe how to change
1025
+** or modify a subscription
1026
+*/
1027
+static const char zUnsubMsg[] =
1028
+@ To changes your subscription settings at %s visit this link:
1029
+@
1030
+@ %s/alerts/%s
1031
+@
1032
+@ To completely unsubscribe from %s, visit the following link:
1033
+@
1034
+@ %s/unsubscribe/%s
1035
+;
1036
+
1037
+/*
1038
+** WEBPAGE: unsubscribe
1039
+**
1040
+** Users visit this page to be delisted from email alerts.
1041
+**
1042
+** If a valid subscriber code is supplied in the name= query parameter,
1043
+** then that subscriber is delisted.
1044
+**
1045
+** Otherwise, If the users is logged in, then they are redirected
1046
+** to the /alerts page where they have an unsubscribe button.
1047
+**
1048
+** Non-logged-in users with no name= query parameter are invited to enter
1049
+** an email address to which will be sent the unsubscribe link that
1050
+** contains the correct subscriber code.
1051
+*/
1052
+void unsubscribe_page(void){
1053
+ const char *zName = P("name");
1054
+ char *zErr = 0;
1055
+ int eErr = 0;
1056
+ unsigned int uSeed;
1057
+ const char *zDecoded;
1058
+ char *zCaptcha = 0;
1059
+ int dx;
1060
+ int bSubmit;
1061
+ const char *zEAddr;
1062
+ char *zCode = 0;
1063
+
1064
+ /* If a valid subscriber code is supplied, then unsubscribe immediately.
1065
+ */
1066
+ if( zName
1067
+ && db_exists("SELECT 1 FROM subscriber WHERE subscriberCode=hextoblob(%Q)",
1068
+ zName)
1069
+ ){
1070
+ email_unsubscribe(zName);
1071
+ return;
1072
+ }
1073
+
1074
+ /* Logged in users are redirected to the /alerts page */
1075
+ login_check_credentials();
1076
+ if( login_is_individual() ){
1077
+ cgi_redirectf("%R/alerts");
1078
+ return;
1079
+ }
1080
+
1081
+ zEAddr = PD("e","");
1082
+ dx = atoi(PD("dx","0"));
1083
+ bSubmit = P("submit")!=0 && P("e")!=0 && cgi_csrf_safe(1);
1084
+ if( bSubmit ){
1085
+ if( !captcha_is_correct(1) ){
1086
+ eErr = 2;
1087
+ zErr = mprintf("enter the security code shown below");
1088
+ bSubmit = 0;
1089
+ }
1090
+ }
1091
+ if( bSubmit ){
1092
+ zCode = db_text(0,"SELECT hex(subscriberCode) FROM subscriber"
1093
+ " WHERE semail=%Q", zEAddr);
1094
+ if( zCode==0 ){
1095
+ eErr = 1;
1096
+ zErr = mprintf("not a valid email address");
1097
+ bSubmit = 0;
1098
+ }
1099
+ }
1100
+ if( bSubmit ){
1101
+ /* If we get this far, it means that a valid unsubscribe request has
1102
+ ** been submitted. Send the appropriate email. */
1103
+ Blob hdr, body;
1104
+ blob_init(&hdr,0,0);
1105
+ blob_init(&body,0,0);
1106
+ blob_appendf(&hdr, "To: %s\n", zEAddr);
1107
+ blob_appendf(&hdr, "Subject: Unsubscribe Instructions\n");
1108
+ blob_appendf(&body, zUnsubMsg/*works-like:"%s%s%s%s%s%s"*/,
1109
+ g.zBaseURL, g.zBaseURL, zCode, g.zBaseURL, g.zBaseURL, zCode);
1110
+ email_send(&hdr, &body, 0, 0);
1111
+ style_header("Unsubscribe Instructions Sent");
1112
+ @ <p>An email has been sent to "%h(zEAddr)" that explains how to
1113
+ @ unsubscribe and/or modify your subscription settings</p>
1114
+ style_footer();
1115
+ return;
1116
+ }
1117
+
1118
+ /* Non-logged-in users have to enter an email address to which is
1119
+ ** sent a message containing the unsubscribe link.
1120
+ */
1121
+ style_header("Unsubscribe Request");
1122
+ @ <p>Fill out the form below to request an email message that will
1123
+ @ explain how to unsubscribe and/or change your subscription settings.</p>
1124
+ @
1125
+ form_begin(0, "%R/unsubscribe");
1126
+ @ <table class="subscribe">
1127
+ @ <tr>
1128
+ @ <td class="form_label">Email&nbsp;Address:</td>
1129
+ @ <td><input type="text" name="e" value="%h(zEAddr)" size="30"></td>
1130
+ if( eErr==1 ){
1131
+ @ <td><span class="loginError">&larr; %h(zErr)</span></td>
1132
+ }
1133
+ @ </tr>
1134
+ uSeed = captcha_seed();
1135
+ zDecoded = captcha_decode(uSeed);
1136
+ zCaptcha = captcha_render(zDecoded);
1137
+ @ <tr>
1138
+ @ <td class="form_label">Security Code:</td>
1139
+ @ <td><input type="text" name="captcha" value="" size="30">
1140
+ @ <input type="hidden" name="captchaseed" value="%u(uSeed)"></td>
1141
+ if( eErr==2 ){
1142
+ @ <td><span class="loginError">&larr; %h(zErr)</span></td>
1143
+ }
1144
+ @ </tr>
1145
+ @ <tr>
1146
+ @ <td class="form_label">Options:</td>
1147
+ @ <td><label><input type="radio" name="dx" value="0" %s(dx?"":"checked")>\
1148
+ @ Modify subscription</label><br>
1149
+ @ <label><input type="radio" name="dx" value="1" %s(dx?"checked":"")>\
1150
+ @ Completely unsubscribe</label><br>
1151
+ @ <tr>
1152
+ @ <td></td>
1153
+ @ <td><input type="submit" name="submit" value="Submit"></td>
1154
+ @ </tr>
1155
+ @ </table>
1156
+ @ <div class="captcha"><table class="captcha"><tr><td><pre>
1157
+ @ %h(zCaptcha)
1158
+ @ </pre>
1159
+ @ Enter the 8 characters above in the "Security Code" box
1160
+ @ </td></tr></table></div>
1161
+ @ </form>
1162
+ fossil_free(zErr);
1163
+ style_footer();
1164
+}
10041165
10051166
/*
10061167
** WEBPAGE: subscribers
10071168
**
10081169
** This page, accessible to administrators only,
10091170
--- src/email.c
+++ src/email.c
@@ -152,11 +152,11 @@
152 void setup_email(void){
153 static const char *const azSendMethods[] = {
154 "off", "Disabled",
155 "pipe", "Pipe to a command",
156 "db", "Store in a database",
157 "file", "Store in a directory"
158 };
159 login_check_credentials();
160 if( !g.perm.Setup ){
161 login_needed(0);
162 return;
@@ -571,13 +571,13 @@
571 /*
572 ** Do error checking on a submitted subscription form. Return TRUE
573 ** if the submission is valid. Return false if any problems are seen.
574 */
575 static int subscribe_error_check(
576 int *peErr, /* Type of error */
577 char **pzErr, /* Error message text */
578 int needCaptcha /* True if captcha check needed */
579 ){
580 const char *zEAddr;
581 int i, j, n;
582 char c;
583
@@ -817,10 +817,35 @@
817 }
818 @ </form>
819 fossil_free(zErr);
820 style_footer();
821 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
822
823 /*
824 ** WEBPAGE: alerts
825 **
826 ** Edit email alert and notification settings.
@@ -896,17 +921,11 @@
896 if( !PB("dodelete") ){
897 eErr = 9;
898 zErr = mprintf("Select this checkbox and press \"Unsubscribe\" to"
899 " unsubscribe");
900 }else{
901 db_multi_exec(
902 "DELETE FROM subscriber WHERE subscriberCode=hextoblob(%Q)",
903 zName
904 );
905 style_header("Email Subscription Deleted");
906 @ <p>The email subscription has been deleted</p>
907 style_footer();
908 return;
909 }
910 }
911 db_prepare(&q,
912 "SELECT"
@@ -999,10 +1018,152 @@
999 @ </form>
1000 fossil_free(zErr);
1001 db_finalize(&q);
1002 style_footer();
1003 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1004
1005 /*
1006 ** WEBPAGE: subscribers
1007 **
1008 ** This page, accessible to administrators only,
1009
--- src/email.c
+++ src/email.c
@@ -152,11 +152,11 @@
152 void setup_email(void){
153 static const char *const azSendMethods[] = {
154 "off", "Disabled",
155 "pipe", "Pipe to a command",
156 "db", "Store in a database",
157 "dir", "Store in a directory"
158 };
159 login_check_credentials();
160 if( !g.perm.Setup ){
161 login_needed(0);
162 return;
@@ -571,13 +571,13 @@
571 /*
572 ** Do error checking on a submitted subscription form. Return TRUE
573 ** if the submission is valid. Return false if any problems are seen.
574 */
575 static int subscribe_error_check(
576 int *peErr, /* Type of error */
577 char **pzErr, /* Error message text */
578 int needCaptcha /* True if captcha check needed */
579 ){
580 const char *zEAddr;
581 int i, j, n;
582 char c;
583
@@ -817,10 +817,35 @@
817 }
818 @ </form>
819 fossil_free(zErr);
820 style_footer();
821 }
822
823 /*
824 ** Either shutdown or completely delete a subscription entry given
825 ** by the hex value zName. Then paint a webpage that explains that
826 ** the entry has been removed.
827 */
828 static void email_unsubscribe(const char *zName){
829 char *zEmail;
830 zEmail = db_text(0, "SELECT semail FROM subscriber"
831 " WHERE subscriberCode=hextoblob(%Q)", zName);
832 if( zEmail==0 ){
833 style_header("Unsubscribe Fail");
834 @ <p>Unable to locate a subscriber with the requested key</p>
835 }else{
836 db_multi_exec(
837 "DELETE FROM subscriber WHERE subscriberCode=hextoblob(%Q)",
838 zName
839 );
840 style_header("Unsubscribed");
841 @ <p>The "%h(zEmail)" email address has been delisted.
842 @ All traces of that email address have been removed</p>
843 }
844 style_footer();
845 return;
846 }
847
848 /*
849 ** WEBPAGE: alerts
850 **
851 ** Edit email alert and notification settings.
@@ -896,17 +921,11 @@
921 if( !PB("dodelete") ){
922 eErr = 9;
923 zErr = mprintf("Select this checkbox and press \"Unsubscribe\" to"
924 " unsubscribe");
925 }else{
926 email_unsubscribe(zName);
 
 
 
 
 
 
927 return;
928 }
929 }
930 db_prepare(&q,
931 "SELECT"
@@ -999,10 +1018,152 @@
1018 @ </form>
1019 fossil_free(zErr);
1020 db_finalize(&q);
1021 style_footer();
1022 }
1023
1024 /* This is the message that gets sent to describe how to change
1025 ** or modify a subscription
1026 */
1027 static const char zUnsubMsg[] =
1028 @ To changes your subscription settings at %s visit this link:
1029 @
1030 @ %s/alerts/%s
1031 @
1032 @ To completely unsubscribe from %s, visit the following link:
1033 @
1034 @ %s/unsubscribe/%s
1035 ;
1036
1037 /*
1038 ** WEBPAGE: unsubscribe
1039 **
1040 ** Users visit this page to be delisted from email alerts.
1041 **
1042 ** If a valid subscriber code is supplied in the name= query parameter,
1043 ** then that subscriber is delisted.
1044 **
1045 ** Otherwise, If the users is logged in, then they are redirected
1046 ** to the /alerts page where they have an unsubscribe button.
1047 **
1048 ** Non-logged-in users with no name= query parameter are invited to enter
1049 ** an email address to which will be sent the unsubscribe link that
1050 ** contains the correct subscriber code.
1051 */
1052 void unsubscribe_page(void){
1053 const char *zName = P("name");
1054 char *zErr = 0;
1055 int eErr = 0;
1056 unsigned int uSeed;
1057 const char *zDecoded;
1058 char *zCaptcha = 0;
1059 int dx;
1060 int bSubmit;
1061 const char *zEAddr;
1062 char *zCode = 0;
1063
1064 /* If a valid subscriber code is supplied, then unsubscribe immediately.
1065 */
1066 if( zName
1067 && db_exists("SELECT 1 FROM subscriber WHERE subscriberCode=hextoblob(%Q)",
1068 zName)
1069 ){
1070 email_unsubscribe(zName);
1071 return;
1072 }
1073
1074 /* Logged in users are redirected to the /alerts page */
1075 login_check_credentials();
1076 if( login_is_individual() ){
1077 cgi_redirectf("%R/alerts");
1078 return;
1079 }
1080
1081 zEAddr = PD("e","");
1082 dx = atoi(PD("dx","0"));
1083 bSubmit = P("submit")!=0 && P("e")!=0 && cgi_csrf_safe(1);
1084 if( bSubmit ){
1085 if( !captcha_is_correct(1) ){
1086 eErr = 2;
1087 zErr = mprintf("enter the security code shown below");
1088 bSubmit = 0;
1089 }
1090 }
1091 if( bSubmit ){
1092 zCode = db_text(0,"SELECT hex(subscriberCode) FROM subscriber"
1093 " WHERE semail=%Q", zEAddr);
1094 if( zCode==0 ){
1095 eErr = 1;
1096 zErr = mprintf("not a valid email address");
1097 bSubmit = 0;
1098 }
1099 }
1100 if( bSubmit ){
1101 /* If we get this far, it means that a valid unsubscribe request has
1102 ** been submitted. Send the appropriate email. */
1103 Blob hdr, body;
1104 blob_init(&hdr,0,0);
1105 blob_init(&body,0,0);
1106 blob_appendf(&hdr, "To: %s\n", zEAddr);
1107 blob_appendf(&hdr, "Subject: Unsubscribe Instructions\n");
1108 blob_appendf(&body, zUnsubMsg/*works-like:"%s%s%s%s%s%s"*/,
1109 g.zBaseURL, g.zBaseURL, zCode, g.zBaseURL, g.zBaseURL, zCode);
1110 email_send(&hdr, &body, 0, 0);
1111 style_header("Unsubscribe Instructions Sent");
1112 @ <p>An email has been sent to "%h(zEAddr)" that explains how to
1113 @ unsubscribe and/or modify your subscription settings</p>
1114 style_footer();
1115 return;
1116 }
1117
1118 /* Non-logged-in users have to enter an email address to which is
1119 ** sent a message containing the unsubscribe link.
1120 */
1121 style_header("Unsubscribe Request");
1122 @ <p>Fill out the form below to request an email message that will
1123 @ explain how to unsubscribe and/or change your subscription settings.</p>
1124 @
1125 form_begin(0, "%R/unsubscribe");
1126 @ <table class="subscribe">
1127 @ <tr>
1128 @ <td class="form_label">Email&nbsp;Address:</td>
1129 @ <td><input type="text" name="e" value="%h(zEAddr)" size="30"></td>
1130 if( eErr==1 ){
1131 @ <td><span class="loginError">&larr; %h(zErr)</span></td>
1132 }
1133 @ </tr>
1134 uSeed = captcha_seed();
1135 zDecoded = captcha_decode(uSeed);
1136 zCaptcha = captcha_render(zDecoded);
1137 @ <tr>
1138 @ <td class="form_label">Security Code:</td>
1139 @ <td><input type="text" name="captcha" value="" size="30">
1140 @ <input type="hidden" name="captchaseed" value="%u(uSeed)"></td>
1141 if( eErr==2 ){
1142 @ <td><span class="loginError">&larr; %h(zErr)</span></td>
1143 }
1144 @ </tr>
1145 @ <tr>
1146 @ <td class="form_label">Options:</td>
1147 @ <td><label><input type="radio" name="dx" value="0" %s(dx?"":"checked")>\
1148 @ Modify subscription</label><br>
1149 @ <label><input type="radio" name="dx" value="1" %s(dx?"checked":"")>\
1150 @ Completely unsubscribe</label><br>
1151 @ <tr>
1152 @ <td></td>
1153 @ <td><input type="submit" name="submit" value="Submit"></td>
1154 @ </tr>
1155 @ </table>
1156 @ <div class="captcha"><table class="captcha"><tr><td><pre>
1157 @ %h(zCaptcha)
1158 @ </pre>
1159 @ Enter the 8 characters above in the "Security Code" box
1160 @ </td></tr></table></div>
1161 @ </form>
1162 fossil_free(zErr);
1163 style_footer();
1164 }
1165
1166 /*
1167 ** WEBPAGE: subscribers
1168 **
1169 ** This page, accessible to administrators only,
1170

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button