Fossil SCM

Infrastructure added to support expiring subscriptions when there has been no contact with the recipient in some number of days.

drh 2021-05-31 12:04 trunk
Commit b4bba2ef605cf2a5fc6398d7d022422611f1b6c4a81c14cece388e0278a065f1
2 files changed +77 -20 +6 -6
+77 -20
--- src/alerts.c
+++ src/alerts.c
@@ -291,17 +291,18 @@
291291
@ <hr>
292292
293293
entry_attribute("Subscription Renewal Interval In Days", 8,
294294
"email-renew-interval", "eri", "", 0);
295295
@ <p>
296
- @ If this value is a positive integer N, then email notification
297
- @ subscriptions will be suspended N days after the last known
296
+ @ If this value is a integer N greater than or equal to 14, then email
297
+ @ notification subscriptions will be suspended N days after the last known
298298
@ interaction with the user. This prevents sending notifications
299
- @ to abandoned accounts. If a subscription gets close to expiring
299
+ @ to abandoned accounts. If a subscription comes within 7 days of expiring,
300300
@ a separate email goes out with the daily digest that prompts the
301301
@ subscriber to click on a link to the "/renew" webpage in order to
302
- @ extend their subscription.
302
+ @ extend their subscription. Subscriptions never expire if this setting
303
+ @ is less than 14 or is an empty string.
303304
@ (Property: "email-renew-interval")</p>
304305
@ <hr>
305306
306307
multiple_choice_attribute("Email Send Method", "email-send-method", "esm",
307308
"off", count(azSendMethods)/2, azSendMethods);
@@ -968,10 +969,38 @@
968969
** SETTING: email-subname width=16
969970
** This is a short name used to identifies the repository in the Subject:
970971
** line of email alerts. Traditionally this name is included in square
971972
** brackets. Examples: "[fossil-src]", "[sqlite-src]".
972973
*/
974
+/*
975
+** SETTING: email-renew-interval width=16
976
+** If this setting as an integer N that is 14 or greater then email
977
+** notification is suspected for subscriptions that have a "last contact
978
+** time" of more than N days ago. The "last contact time" is recorded
979
+** in the SUBSCRIBER.LASTCONTACT entry of the database. Logging in,
980
+** sending a forum post, editing a wiki page, changing subscription settings
981
+** at /alerts, or visiting /renew all update the last contact time.
982
+** If this setting is not an integer value or is less than 14 or undefined,
983
+** then subscriptions never expire.
984
+*/
985
+/* X-VARIABLE: email-renew-warning
986
+** X-VARIABLE: email-renew-cutoff
987
+**
988
+** These CONFIG table entries are not considered "settings" since their
989
+** values are computed and updated automatically.
990
+**
991
+** email-renew-cutoff is the lastContact cutoff for subscription. It
992
+** is measured in days since 1970-01-01. If The lastContact time for
993
+** a subscription is less than email-renew-cutoff, then now new emails
994
+** are sent to the subscriber.
995
+**
996
+** email-renew-warning is the time (in days since 1970-01-01) when the
997
+** last batch of "your subscription is about to expire" emails were
998
+** sent out.
999
+**
1000
+** email-renew-cutoff is normally 7 days behind email-renew-warning.
1001
+*/
9731002
/*
9741003
** SETTING: email-send-method width=5 default=off sensitive
9751004
** Determine the method used to send email. Allowed values are
9761005
** "off", "relay", "pipe", "dir", "db", and "stdout". The "off" value
9771006
** means no email is ever sent. The "relay" value means emails are sent
@@ -1040,21 +1069,22 @@
10401069
** Or change the value of a single email setting.
10411070
**
10421071
** status Report on the status of the email alert
10431072
** subsystem
10441073
**
1045
-** subscribers [PATTERN] List all subscribers matching PATTERN.
1074
+** subscribers [PATTERN] List all subscribers matching PATTERN. Either
1075
+** LIKE or GLOB wildcards can be used in PATTERN.
10461076
**
10471077
** test-message TO [OPTS] Send a single email message using whatever
10481078
** email sending mechanism is currently configured.
10491079
** Use this for testing the email notification
10501080
** configuration. Options:
10511081
**
1052
-** --body FILENAME
1053
-** --smtp-trace
1054
-** --stdout
1055
-** -S|--subject SUBJECT
1082
+** --body FILENAME Content from FILENAME
1083
+** --smtp-trace Trace SMTP processing
1084
+** --stdout Send msg to stdout
1085
+** -S|--subject SUBJECT Message "subject:"
10561086
**
10571087
** unsubscribe EMAIL Remove a single subscriber with the given EMAIL.
10581088
*/
10591089
void alert_cmd(void){
10601090
const char *zCmd;
@@ -1963,14 +1993,16 @@
19631993
}
19641994
19651995
/*
19661996
** WEBPAGE: renew
19671997
**
1968
-** Users visit this page to update the lastContact date on their
1969
-** subscription. This prevents their subscriptions from expiring.
1970
-**
1971
-** A valid subscriber code is supplied in the name= query parameter.
1998
+** Users visit this page to update the last-contact date on their
1999
+** subscription. The last-contact date is the day that the subscriber
2000
+** last interacted with the repository. If the name= query parameter
2001
+** (or POST parameter) contains a valid subscriber code, then the last-contact
2002
+** subscription associated with that subscriber code is updated to be the
2003
+** current date.
19722004
*/
19732005
void renewal_page(void){
19742006
const char *zName = P("name");
19752007
int iInterval = db_get_int("email-renew-interval", 0);
19762008
Stmt s;
@@ -2182,10 +2214,14 @@
21822214
Stmt q;
21832215
sqlite3_int64 iNow;
21842216
int nTotal;
21852217
int nPending;
21862218
int nDel = 0;
2219
+ int iCutoff = db_get_int("email-renew-cutoff",0);
2220
+ int iWarning = db_get_int("email-renew-warning",0);
2221
+ char zCutoffClr[8];
2222
+ char zWarnClr[8];
21872223
if( alert_webpages_disabled() ) return;
21882224
login_check_credentials();
21892225
if( !g.perm.Admin ){
21902226
login_needed(0);
21912227
return;
@@ -2240,10 +2276,12 @@
22402276
style_submenu_element("Show All","%R/subscribers");
22412277
}
22422278
blob_append_sql(&sql," ORDER BY mtime DESC");
22432279
db_prepare_blob(&q, &sql);
22442280
iNow = time(0);
2281
+ memcpy(zCutoffClr, hash_color("A"), sizeof(zCutoffClr));
2282
+ memcpy(zWarnClr, hash_color("HIJ"), sizeof(zWarnClr));
22452283
@ <table border='1' class='sortable' \
22462284
@ data-init-sort='6' data-column-types='tttttKKt'>
22472285
@ <thead>
22482286
@ <tr>
22492287
@ <th>Email
@@ -2273,11 +2311,19 @@
22732311
}else{
22742312
@ <td>%h(zUname)</td>
22752313
}
22762314
@ <td>%s(db_column_int(&q,4)?"yes":"pending")</td>
22772315
@ <td data-sortkey='%010llx(iMtime)'>%z(human_readable_age(rAge))</td>
2278
- @ <td data-sortkey='%010llx(iContact)'>%z(human_readable_age(rContact))</td>
2316
+ @ <td data-sortkey='%010llx(iContact)'>\
2317
+ if( iContact>iWarning ){
2318
+ @ <span>\
2319
+ }else if( iContact>iCutoff ){
2320
+ @ <span style='background-color:%s(zWarnClr);'>\
2321
+ }else{
2322
+ @ <span style='background-color:%s(zCutoffClr);'>\
2323
+ }
2324
+ @ %z(human_readable_age(rContact))</td>
22792325
@ <td>%h(db_column_text(&q,7))</td>
22802326
@ </tr>
22812327
}
22822328
@ </tbody></table>
22832329
db_finalize(&q);
@@ -2530,14 +2576,22 @@
25302576
** Usage: %fossil test-alert EVENTID ...
25312577
**
25322578
** Generate the text of an email alert for all of the EVENTIDs
25332579
** listed on the command-line. Or if no events are listed on the
25342580
** command line, generate text for all events named in the
2535
-** pending_alert table.
2581
+** pending_alert table. The text of the email alerts appears on
2582
+** standard output.
2583
+**
2584
+** This command is intended for testing and debugging Fossil itself,
2585
+** for example when enhancing the email alert system or fixing bugs
2586
+** in the email alert system. If you are not making changes to the
2587
+** Fossil source code, this command is probably not useful to you.
25362588
**
2537
-** This command is intended for testing and debugging the logic
2538
-** that generates email alert text.
2589
+** EVENTIDs are text. The first character is 'c', 'f', 't', or 'w'
2590
+** for check-in, forum, ticket, or wiki. The remaining text is a
2591
+** integer that references the EVENT.OBJID value for the event.
2592
+** Run /timeline?showid to see these OBJID values.
25392593
**
25402594
** Options:
25412595
**
25422596
** --digest Generate digest alert text
25432597
** --needmod Assume all events are pending moderator approval
@@ -2775,13 +2829,16 @@
27752829
" hex(subscriberCode)," /* 0 */
27762830
" semail," /* 1 */
27772831
" ssub," /* 2 */
27782832
" fullcap(user.cap)" /* 3 */
27792833
" FROM subscriber LEFT JOIN user ON (login=suname)"
2780
- " WHERE sverified AND NOT sdonotcall"
2781
- " AND sdigest IS %s",
2782
- zDigest/*safe-for-%s*/
2834
+ " WHERE sverified"
2835
+ " AND NOT sdonotcall"
2836
+ " AND sdigest IS %s"
2837
+ " AND coalesce(subscriber.lastContact,subscriber.mtime)>=%d",
2838
+ zDigest/*safe-for-%s*/,
2839
+ db_get_int("email-renew-cutoff",0)
27832840
);
27842841
while( db_step(&q)==SQLITE_ROW ){
27852842
const char *zCode = db_column_text(&q, 0);
27862843
const char *zSub = db_column_text(&q, 2);
27872844
const char *zEmail = db_column_text(&q, 1);
27882845
--- src/alerts.c
+++ src/alerts.c
@@ -291,17 +291,18 @@
291 @ <hr>
292
293 entry_attribute("Subscription Renewal Interval In Days", 8,
294 "email-renew-interval", "eri", "", 0);
295 @ <p>
296 @ If this value is a positive integer N, then email notification
297 @ subscriptions will be suspended N days after the last known
298 @ interaction with the user. This prevents sending notifications
299 @ to abandoned accounts. If a subscription gets close to expiring
300 @ a separate email goes out with the daily digest that prompts the
301 @ subscriber to click on a link to the "/renew" webpage in order to
302 @ extend their subscription.
 
303 @ (Property: "email-renew-interval")</p>
304 @ <hr>
305
306 multiple_choice_attribute("Email Send Method", "email-send-method", "esm",
307 "off", count(azSendMethods)/2, azSendMethods);
@@ -968,10 +969,38 @@
968 ** SETTING: email-subname width=16
969 ** This is a short name used to identifies the repository in the Subject:
970 ** line of email alerts. Traditionally this name is included in square
971 ** brackets. Examples: "[fossil-src]", "[sqlite-src]".
972 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
973 /*
974 ** SETTING: email-send-method width=5 default=off sensitive
975 ** Determine the method used to send email. Allowed values are
976 ** "off", "relay", "pipe", "dir", "db", and "stdout". The "off" value
977 ** means no email is ever sent. The "relay" value means emails are sent
@@ -1040,21 +1069,22 @@
1040 ** Or change the value of a single email setting.
1041 **
1042 ** status Report on the status of the email alert
1043 ** subsystem
1044 **
1045 ** subscribers [PATTERN] List all subscribers matching PATTERN.
 
1046 **
1047 ** test-message TO [OPTS] Send a single email message using whatever
1048 ** email sending mechanism is currently configured.
1049 ** Use this for testing the email notification
1050 ** configuration. Options:
1051 **
1052 ** --body FILENAME
1053 ** --smtp-trace
1054 ** --stdout
1055 ** -S|--subject SUBJECT
1056 **
1057 ** unsubscribe EMAIL Remove a single subscriber with the given EMAIL.
1058 */
1059 void alert_cmd(void){
1060 const char *zCmd;
@@ -1963,14 +1993,16 @@
1963 }
1964
1965 /*
1966 ** WEBPAGE: renew
1967 **
1968 ** Users visit this page to update the lastContact date on their
1969 ** subscription. This prevents their subscriptions from expiring.
1970 **
1971 ** A valid subscriber code is supplied in the name= query parameter.
 
 
1972 */
1973 void renewal_page(void){
1974 const char *zName = P("name");
1975 int iInterval = db_get_int("email-renew-interval", 0);
1976 Stmt s;
@@ -2182,10 +2214,14 @@
2182 Stmt q;
2183 sqlite3_int64 iNow;
2184 int nTotal;
2185 int nPending;
2186 int nDel = 0;
 
 
 
 
2187 if( alert_webpages_disabled() ) return;
2188 login_check_credentials();
2189 if( !g.perm.Admin ){
2190 login_needed(0);
2191 return;
@@ -2240,10 +2276,12 @@
2240 style_submenu_element("Show All","%R/subscribers");
2241 }
2242 blob_append_sql(&sql," ORDER BY mtime DESC");
2243 db_prepare_blob(&q, &sql);
2244 iNow = time(0);
 
 
2245 @ <table border='1' class='sortable' \
2246 @ data-init-sort='6' data-column-types='tttttKKt'>
2247 @ <thead>
2248 @ <tr>
2249 @ <th>Email
@@ -2273,11 +2311,19 @@
2273 }else{
2274 @ <td>%h(zUname)</td>
2275 }
2276 @ <td>%s(db_column_int(&q,4)?"yes":"pending")</td>
2277 @ <td data-sortkey='%010llx(iMtime)'>%z(human_readable_age(rAge))</td>
2278 @ <td data-sortkey='%010llx(iContact)'>%z(human_readable_age(rContact))</td>
 
 
 
 
 
 
 
 
2279 @ <td>%h(db_column_text(&q,7))</td>
2280 @ </tr>
2281 }
2282 @ </tbody></table>
2283 db_finalize(&q);
@@ -2530,14 +2576,22 @@
2530 ** Usage: %fossil test-alert EVENTID ...
2531 **
2532 ** Generate the text of an email alert for all of the EVENTIDs
2533 ** listed on the command-line. Or if no events are listed on the
2534 ** command line, generate text for all events named in the
2535 ** pending_alert table.
 
 
 
 
 
 
2536 **
2537 ** This command is intended for testing and debugging the logic
2538 ** that generates email alert text.
 
 
2539 **
2540 ** Options:
2541 **
2542 ** --digest Generate digest alert text
2543 ** --needmod Assume all events are pending moderator approval
@@ -2775,13 +2829,16 @@
2775 " hex(subscriberCode)," /* 0 */
2776 " semail," /* 1 */
2777 " ssub," /* 2 */
2778 " fullcap(user.cap)" /* 3 */
2779 " FROM subscriber LEFT JOIN user ON (login=suname)"
2780 " WHERE sverified AND NOT sdonotcall"
2781 " AND sdigest IS %s",
2782 zDigest/*safe-for-%s*/
 
 
 
2783 );
2784 while( db_step(&q)==SQLITE_ROW ){
2785 const char *zCode = db_column_text(&q, 0);
2786 const char *zSub = db_column_text(&q, 2);
2787 const char *zEmail = db_column_text(&q, 1);
2788
--- src/alerts.c
+++ src/alerts.c
@@ -291,17 +291,18 @@
291 @ <hr>
292
293 entry_attribute("Subscription Renewal Interval In Days", 8,
294 "email-renew-interval", "eri", "", 0);
295 @ <p>
296 @ If this value is a integer N greater than or equal to 14, then email
297 @ notification subscriptions will be suspended N days after the last known
298 @ interaction with the user. This prevents sending notifications
299 @ to abandoned accounts. If a subscription comes within 7 days of expiring,
300 @ a separate email goes out with the daily digest that prompts the
301 @ subscriber to click on a link to the "/renew" webpage in order to
302 @ extend their subscription. Subscriptions never expire if this setting
303 @ is less than 14 or is an empty string.
304 @ (Property: "email-renew-interval")</p>
305 @ <hr>
306
307 multiple_choice_attribute("Email Send Method", "email-send-method", "esm",
308 "off", count(azSendMethods)/2, azSendMethods);
@@ -968,10 +969,38 @@
969 ** SETTING: email-subname width=16
970 ** This is a short name used to identifies the repository in the Subject:
971 ** line of email alerts. Traditionally this name is included in square
972 ** brackets. Examples: "[fossil-src]", "[sqlite-src]".
973 */
974 /*
975 ** SETTING: email-renew-interval width=16
976 ** If this setting as an integer N that is 14 or greater then email
977 ** notification is suspected for subscriptions that have a "last contact
978 ** time" of more than N days ago. The "last contact time" is recorded
979 ** in the SUBSCRIBER.LASTCONTACT entry of the database. Logging in,
980 ** sending a forum post, editing a wiki page, changing subscription settings
981 ** at /alerts, or visiting /renew all update the last contact time.
982 ** If this setting is not an integer value or is less than 14 or undefined,
983 ** then subscriptions never expire.
984 */
985 /* X-VARIABLE: email-renew-warning
986 ** X-VARIABLE: email-renew-cutoff
987 **
988 ** These CONFIG table entries are not considered "settings" since their
989 ** values are computed and updated automatically.
990 **
991 ** email-renew-cutoff is the lastContact cutoff for subscription. It
992 ** is measured in days since 1970-01-01. If The lastContact time for
993 ** a subscription is less than email-renew-cutoff, then now new emails
994 ** are sent to the subscriber.
995 **
996 ** email-renew-warning is the time (in days since 1970-01-01) when the
997 ** last batch of "your subscription is about to expire" emails were
998 ** sent out.
999 **
1000 ** email-renew-cutoff is normally 7 days behind email-renew-warning.
1001 */
1002 /*
1003 ** SETTING: email-send-method width=5 default=off sensitive
1004 ** Determine the method used to send email. Allowed values are
1005 ** "off", "relay", "pipe", "dir", "db", and "stdout". The "off" value
1006 ** means no email is ever sent. The "relay" value means emails are sent
@@ -1040,21 +1069,22 @@
1069 ** Or change the value of a single email setting.
1070 **
1071 ** status Report on the status of the email alert
1072 ** subsystem
1073 **
1074 ** subscribers [PATTERN] List all subscribers matching PATTERN. Either
1075 ** LIKE or GLOB wildcards can be used in PATTERN.
1076 **
1077 ** test-message TO [OPTS] Send a single email message using whatever
1078 ** email sending mechanism is currently configured.
1079 ** Use this for testing the email notification
1080 ** configuration. Options:
1081 **
1082 ** --body FILENAME Content from FILENAME
1083 ** --smtp-trace Trace SMTP processing
1084 ** --stdout Send msg to stdout
1085 ** -S|--subject SUBJECT Message "subject:"
1086 **
1087 ** unsubscribe EMAIL Remove a single subscriber with the given EMAIL.
1088 */
1089 void alert_cmd(void){
1090 const char *zCmd;
@@ -1963,14 +1993,16 @@
1993 }
1994
1995 /*
1996 ** WEBPAGE: renew
1997 **
1998 ** Users visit this page to update the last-contact date on their
1999 ** subscription. The last-contact date is the day that the subscriber
2000 ** last interacted with the repository. If the name= query parameter
2001 ** (or POST parameter) contains a valid subscriber code, then the last-contact
2002 ** subscription associated with that subscriber code is updated to be the
2003 ** current date.
2004 */
2005 void renewal_page(void){
2006 const char *zName = P("name");
2007 int iInterval = db_get_int("email-renew-interval", 0);
2008 Stmt s;
@@ -2182,10 +2214,14 @@
2214 Stmt q;
2215 sqlite3_int64 iNow;
2216 int nTotal;
2217 int nPending;
2218 int nDel = 0;
2219 int iCutoff = db_get_int("email-renew-cutoff",0);
2220 int iWarning = db_get_int("email-renew-warning",0);
2221 char zCutoffClr[8];
2222 char zWarnClr[8];
2223 if( alert_webpages_disabled() ) return;
2224 login_check_credentials();
2225 if( !g.perm.Admin ){
2226 login_needed(0);
2227 return;
@@ -2240,10 +2276,12 @@
2276 style_submenu_element("Show All","%R/subscribers");
2277 }
2278 blob_append_sql(&sql," ORDER BY mtime DESC");
2279 db_prepare_blob(&q, &sql);
2280 iNow = time(0);
2281 memcpy(zCutoffClr, hash_color("A"), sizeof(zCutoffClr));
2282 memcpy(zWarnClr, hash_color("HIJ"), sizeof(zWarnClr));
2283 @ <table border='1' class='sortable' \
2284 @ data-init-sort='6' data-column-types='tttttKKt'>
2285 @ <thead>
2286 @ <tr>
2287 @ <th>Email
@@ -2273,11 +2311,19 @@
2311 }else{
2312 @ <td>%h(zUname)</td>
2313 }
2314 @ <td>%s(db_column_int(&q,4)?"yes":"pending")</td>
2315 @ <td data-sortkey='%010llx(iMtime)'>%z(human_readable_age(rAge))</td>
2316 @ <td data-sortkey='%010llx(iContact)'>\
2317 if( iContact>iWarning ){
2318 @ <span>\
2319 }else if( iContact>iCutoff ){
2320 @ <span style='background-color:%s(zWarnClr);'>\
2321 }else{
2322 @ <span style='background-color:%s(zCutoffClr);'>\
2323 }
2324 @ %z(human_readable_age(rContact))</td>
2325 @ <td>%h(db_column_text(&q,7))</td>
2326 @ </tr>
2327 }
2328 @ </tbody></table>
2329 db_finalize(&q);
@@ -2530,14 +2576,22 @@
2576 ** Usage: %fossil test-alert EVENTID ...
2577 **
2578 ** Generate the text of an email alert for all of the EVENTIDs
2579 ** listed on the command-line. Or if no events are listed on the
2580 ** command line, generate text for all events named in the
2581 ** pending_alert table. The text of the email alerts appears on
2582 ** standard output.
2583 **
2584 ** This command is intended for testing and debugging Fossil itself,
2585 ** for example when enhancing the email alert system or fixing bugs
2586 ** in the email alert system. If you are not making changes to the
2587 ** Fossil source code, this command is probably not useful to you.
2588 **
2589 ** EVENTIDs are text. The first character is 'c', 'f', 't', or 'w'
2590 ** for check-in, forum, ticket, or wiki. The remaining text is a
2591 ** integer that references the EVENT.OBJID value for the event.
2592 ** Run /timeline?showid to see these OBJID values.
2593 **
2594 ** Options:
2595 **
2596 ** --digest Generate digest alert text
2597 ** --needmod Assume all events are pending moderator approval
@@ -2775,13 +2829,16 @@
2829 " hex(subscriberCode)," /* 0 */
2830 " semail," /* 1 */
2831 " ssub," /* 2 */
2832 " fullcap(user.cap)" /* 3 */
2833 " FROM subscriber LEFT JOIN user ON (login=suname)"
2834 " WHERE sverified"
2835 " AND NOT sdonotcall"
2836 " AND sdigest IS %s"
2837 " AND coalesce(subscriber.lastContact,subscriber.mtime)>=%d",
2838 zDigest/*safe-for-%s*/,
2839 db_get_int("email-renew-cutoff",0)
2840 );
2841 while( db_step(&q)==SQLITE_ROW ){
2842 const char *zCode = db_column_text(&q, 0);
2843 const char *zSub = db_column_text(&q, 2);
2844 const char *zEmail = db_column_text(&q, 1);
2845
+6 -6
--- www/alerts.md
+++ www/alerts.md
@@ -551,10 +551,11 @@
551551
Web pages available to users and subscribers:
552552
553553
* The [`/subscribe`](/help?cmd=/subscribe) page
554554
* The [`/alerts`](/help?cmd=/alerts) page
555555
* The [`/unsubscribe`](/help?cmd=/unsubscribe) page
556
+ * The [`/renew`](/help?cmd=/renew) page
556557
* The [`/contact_admin`](/help?cmd=/contact_admin) page
557558
558559
Administrator-only web pages:
559560
560561
* The [`/setup_notification`](/help?cmd=/setup_notification) page
@@ -574,11 +575,11 @@
574575
575576
576577
<a id="datades"></a>
577578
### Data Design
578579
579
-There are three new tables in the repository database, starting with
580
+There are two new tables in the repository database, starting with
580581
Fossil 2.7. These tables are not created in new repositories by
581582
default. The tables only come into existence as needed when email
582583
alerts are configured and used.
583584
584585
@@ -599,15 +600,14 @@
599600
and records timeline entries. In other words, there is one
600601
row in the EVENT table for each possible timeline entry. The
601602
PENDING\_ALERT table refers to EVENT table entries for which
602603
we might need to send alert emails.
603604
604
- * <b>EMAIL\_BOUNCE</b> →
605
- This table is intended to record email bounce history so that
606
- subscribers with excessive bounces can be turned off. That
607
- logic has not yet been implemented so the EMAIL\_BOUNCE table
608
- is currently unused.
605
+There was a third table "EMAIL_BOUNCE" in Fossil versions 2.7 through 2.14.
606
+That table was intended to record email bounce history so that
607
+subscribers with excessive bounces can be turned off. But that feature
608
+was never implemented and the table was removed in Fossil 2.15.
609609
610610
As pointed out above, ["subscribers" are distinct from "users"](#uvs).
611611
The SUBSCRIBER.SUNAME field is the optional linkage between users and
612612
subscribers.
613613
614614
--- www/alerts.md
+++ www/alerts.md
@@ -551,10 +551,11 @@
551 Web pages available to users and subscribers:
552
553 * The [`/subscribe`](/help?cmd=/subscribe) page
554 * The [`/alerts`](/help?cmd=/alerts) page
555 * The [`/unsubscribe`](/help?cmd=/unsubscribe) page
 
556 * The [`/contact_admin`](/help?cmd=/contact_admin) page
557
558 Administrator-only web pages:
559
560 * The [`/setup_notification`](/help?cmd=/setup_notification) page
@@ -574,11 +575,11 @@
574
575
576 <a id="datades"></a>
577 ### Data Design
578
579 There are three new tables in the repository database, starting with
580 Fossil 2.7. These tables are not created in new repositories by
581 default. The tables only come into existence as needed when email
582 alerts are configured and used.
583
584
@@ -599,15 +600,14 @@
599 and records timeline entries. In other words, there is one
600 row in the EVENT table for each possible timeline entry. The
601 PENDING\_ALERT table refers to EVENT table entries for which
602 we might need to send alert emails.
603
604 * <b>EMAIL\_BOUNCE</b> →
605 This table is intended to record email bounce history so that
606 subscribers with excessive bounces can be turned off. That
607 logic has not yet been implemented so the EMAIL\_BOUNCE table
608 is currently unused.
609
610 As pointed out above, ["subscribers" are distinct from "users"](#uvs).
611 The SUBSCRIBER.SUNAME field is the optional linkage between users and
612 subscribers.
613
614
--- www/alerts.md
+++ www/alerts.md
@@ -551,10 +551,11 @@
551 Web pages available to users and subscribers:
552
553 * The [`/subscribe`](/help?cmd=/subscribe) page
554 * The [`/alerts`](/help?cmd=/alerts) page
555 * The [`/unsubscribe`](/help?cmd=/unsubscribe) page
556 * The [`/renew`](/help?cmd=/renew) page
557 * The [`/contact_admin`](/help?cmd=/contact_admin) page
558
559 Administrator-only web pages:
560
561 * The [`/setup_notification`](/help?cmd=/setup_notification) page
@@ -574,11 +575,11 @@
575
576
577 <a id="datades"></a>
578 ### Data Design
579
580 There are two new tables in the repository database, starting with
581 Fossil 2.7. These tables are not created in new repositories by
582 default. The tables only come into existence as needed when email
583 alerts are configured and used.
584
585
@@ -599,15 +600,14 @@
600 and records timeline entries. In other words, there is one
601 row in the EVENT table for each possible timeline entry. The
602 PENDING\_ALERT table refers to EVENT table entries for which
603 we might need to send alert emails.
604
605 There was a third table "EMAIL_BOUNCE" in Fossil versions 2.7 through 2.14.
606 That table was intended to record email bounce history so that
607 subscribers with excessive bounces can be turned off. But that feature
608 was never implemented and the table was removed in Fossil 2.15.
 
609
610 As pointed out above, ["subscribers" are distinct from "users"](#uvs).
611 The SUBSCRIBER.SUNAME field is the optional linkage between users and
612 subscribers.
613
614

Keyboard Shortcuts

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