Fossil

Check-in [f9116088]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the /unsubscribe page.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | email-alerts
Files: files | file ages | folders
SHA3-256: f9116088243353b0f072c81061cb80a8cbd123a27633872d879d5ec7413bfac7
User & Date: drh 2018-06-22 03:17:00
Context
2018-06-22
12:25
Make sure the content of outbound email messages always ends with a newline. check-in: b7003483 user: drh tags: email-alerts
03:17
Add the /unsubscribe page. check-in: f9116088 user: drh tags: email-alerts
01:28
Fix harmless compiler warnings. check-in: 5fde17bb user: drh tags: email-alerts
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/email.c.

   150    150   ** Administrative page for configuring and controlling email notification
   151    151   */
   152    152   void setup_email(void){
   153    153     static const char *const azSendMethods[] = {
   154    154       "off",  "Disabled",
   155    155       "pipe", "Pipe to a command",
   156    156       "db",   "Store in a database",
   157         -    "file", "Store in a directory"
          157  +    "dir",  "Store in a directory"
   158    158     };
   159    159     login_check_credentials();
   160    160     if( !g.perm.Setup ){
   161    161       login_needed(0);
   162    162       return;
   163    163     }
   164    164     db_begin_transaction();
................................................................................
   569    569   }
   570    570   
   571    571   /*
   572    572   ** Do error checking on a submitted subscription form.  Return TRUE
   573    573   ** if the submission is valid.  Return false if any problems are seen.
   574    574   */
   575    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 */
          576  +  int *peErr,           /* Type of error */
          577  +  char **pzErr,         /* Error message text */
          578  +  int needCaptcha       /* True if captcha check needed */
   579    579   ){
   580    580     const char *zEAddr;
   581    581     int i, j, n;
   582    582     char c;
   583    583   
   584    584     *peErr = 0;
   585    585     *pzErr = 0;
................................................................................
   815    815       @ Enter the 8 characters above in the "Security Code" box
   816    816       @ </td></tr></table></div>
   817    817     }
   818    818     @ </form>
   819    819     fossil_free(zErr);
   820    820     style_footer();
   821    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  +}
   822    847   
   823    848   /*
   824    849   ** WEBPAGE: alerts
   825    850   **
   826    851   ** Edit email alert and notification settings.
   827    852   **
   828    853   ** The subscriber entry is identified in either of two ways:
................................................................................
   894    919     }
   895    920     if( P("delete")!=0 && cgi_csrf_safe(1) ){
   896    921       if( !PB("dodelete") ){
   897    922         eErr = 9;
   898    923         zErr = mprintf("Select this checkbox and press \"Unsubscribe\" to"
   899    924                        " unsubscribe");
   900    925       }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);
   908    927         return;
   909    928       }
   910    929     }
   911    930     db_prepare(&q,
   912    931       "SELECT"
   913    932       "  semail,"
   914    933       "  sverified,"
................................................................................
   997   1016     @ </tr>
   998   1017     @ </table>
   999   1018     @ </form>
  1000   1019     fossil_free(zErr);
  1001   1020     db_finalize(&q);
  1002   1021     style_footer();
  1003   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  +}
  1004   1165   
  1005   1166   /*
  1006   1167   ** WEBPAGE: subscribers
  1007   1168   **
  1008   1169   ** This page, accessible to administrators only,
  1009   1170   ** shows a list of email notification email addresses with
  1010   1171   ** links to facilities for editing.