Fossil SCM
Infrastructure added to support expiring subscriptions when there has been no contact with the recipient in some number of days.
Commit
b4bba2ef605cf2a5fc6398d7d022422611f1b6c4a81c14cece388e0278a065f1
Parent
efb602b7de15115…
2 files changed
+77
-20
+6
-6
+77
-20
| --- src/alerts.c | ||
| +++ src/alerts.c | ||
| @@ -291,17 +291,18 @@ | ||
| 291 | 291 | @ <hr> |
| 292 | 292 | |
| 293 | 293 | entry_attribute("Subscription Renewal Interval In Days", 8, |
| 294 | 294 | "email-renew-interval", "eri", "", 0); |
| 295 | 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 | |
| 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 | 298 | @ 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, | |
| 300 | 300 | @ a separate email goes out with the daily digest that prompts the |
| 301 | 301 | @ 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. | |
| 303 | 304 | @ (Property: "email-renew-interval")</p> |
| 304 | 305 | @ <hr> |
| 305 | 306 | |
| 306 | 307 | multiple_choice_attribute("Email Send Method", "email-send-method", "esm", |
| 307 | 308 | "off", count(azSendMethods)/2, azSendMethods); |
| @@ -968,10 +969,38 @@ | ||
| 968 | 969 | ** SETTING: email-subname width=16 |
| 969 | 970 | ** This is a short name used to identifies the repository in the Subject: |
| 970 | 971 | ** line of email alerts. Traditionally this name is included in square |
| 971 | 972 | ** brackets. Examples: "[fossil-src]", "[sqlite-src]". |
| 972 | 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 | +*/ | |
| 973 | 1002 | /* |
| 974 | 1003 | ** SETTING: email-send-method width=5 default=off sensitive |
| 975 | 1004 | ** Determine the method used to send email. Allowed values are |
| 976 | 1005 | ** "off", "relay", "pipe", "dir", "db", and "stdout". The "off" value |
| 977 | 1006 | ** means no email is ever sent. The "relay" value means emails are sent |
| @@ -1040,21 +1069,22 @@ | ||
| 1040 | 1069 | ** Or change the value of a single email setting. |
| 1041 | 1070 | ** |
| 1042 | 1071 | ** status Report on the status of the email alert |
| 1043 | 1072 | ** subsystem |
| 1044 | 1073 | ** |
| 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. | |
| 1046 | 1076 | ** |
| 1047 | 1077 | ** test-message TO [OPTS] Send a single email message using whatever |
| 1048 | 1078 | ** email sending mechanism is currently configured. |
| 1049 | 1079 | ** Use this for testing the email notification |
| 1050 | 1080 | ** configuration. Options: |
| 1051 | 1081 | ** |
| 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:" | |
| 1056 | 1086 | ** |
| 1057 | 1087 | ** unsubscribe EMAIL Remove a single subscriber with the given EMAIL. |
| 1058 | 1088 | */ |
| 1059 | 1089 | void alert_cmd(void){ |
| 1060 | 1090 | const char *zCmd; |
| @@ -1963,14 +1993,16 @@ | ||
| 1963 | 1993 | } |
| 1964 | 1994 | |
| 1965 | 1995 | /* |
| 1966 | 1996 | ** WEBPAGE: renew |
| 1967 | 1997 | ** |
| 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. | |
| 1972 | 2004 | */ |
| 1973 | 2005 | void renewal_page(void){ |
| 1974 | 2006 | const char *zName = P("name"); |
| 1975 | 2007 | int iInterval = db_get_int("email-renew-interval", 0); |
| 1976 | 2008 | Stmt s; |
| @@ -2182,10 +2214,14 @@ | ||
| 2182 | 2214 | Stmt q; |
| 2183 | 2215 | sqlite3_int64 iNow; |
| 2184 | 2216 | int nTotal; |
| 2185 | 2217 | int nPending; |
| 2186 | 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]; | |
| 2187 | 2223 | if( alert_webpages_disabled() ) return; |
| 2188 | 2224 | login_check_credentials(); |
| 2189 | 2225 | if( !g.perm.Admin ){ |
| 2190 | 2226 | login_needed(0); |
| 2191 | 2227 | return; |
| @@ -2240,10 +2276,12 @@ | ||
| 2240 | 2276 | style_submenu_element("Show All","%R/subscribers"); |
| 2241 | 2277 | } |
| 2242 | 2278 | blob_append_sql(&sql," ORDER BY mtime DESC"); |
| 2243 | 2279 | db_prepare_blob(&q, &sql); |
| 2244 | 2280 | iNow = time(0); |
| 2281 | + memcpy(zCutoffClr, hash_color("A"), sizeof(zCutoffClr)); | |
| 2282 | + memcpy(zWarnClr, hash_color("HIJ"), sizeof(zWarnClr)); | |
| 2245 | 2283 | @ <table border='1' class='sortable' \ |
| 2246 | 2284 | @ data-init-sort='6' data-column-types='tttttKKt'> |
| 2247 | 2285 | @ <thead> |
| 2248 | 2286 | @ <tr> |
| 2249 | 2287 | @ <th>Email |
| @@ -2273,11 +2311,19 @@ | ||
| 2273 | 2311 | }else{ |
| 2274 | 2312 | @ <td>%h(zUname)</td> |
| 2275 | 2313 | } |
| 2276 | 2314 | @ <td>%s(db_column_int(&q,4)?"yes":"pending")</td> |
| 2277 | 2315 | @ <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> | |
| 2279 | 2325 | @ <td>%h(db_column_text(&q,7))</td> |
| 2280 | 2326 | @ </tr> |
| 2281 | 2327 | } |
| 2282 | 2328 | @ </tbody></table> |
| 2283 | 2329 | db_finalize(&q); |
| @@ -2530,14 +2576,22 @@ | ||
| 2530 | 2576 | ** Usage: %fossil test-alert EVENTID ... |
| 2531 | 2577 | ** |
| 2532 | 2578 | ** Generate the text of an email alert for all of the EVENTIDs |
| 2533 | 2579 | ** listed on the command-line. Or if no events are listed on the |
| 2534 | 2580 | ** 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. | |
| 2536 | 2588 | ** |
| 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. | |
| 2539 | 2593 | ** |
| 2540 | 2594 | ** Options: |
| 2541 | 2595 | ** |
| 2542 | 2596 | ** --digest Generate digest alert text |
| 2543 | 2597 | ** --needmod Assume all events are pending moderator approval |
| @@ -2775,13 +2829,16 @@ | ||
| 2775 | 2829 | " hex(subscriberCode)," /* 0 */ |
| 2776 | 2830 | " semail," /* 1 */ |
| 2777 | 2831 | " ssub," /* 2 */ |
| 2778 | 2832 | " fullcap(user.cap)" /* 3 */ |
| 2779 | 2833 | " 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) | |
| 2783 | 2840 | ); |
| 2784 | 2841 | while( db_step(&q)==SQLITE_ROW ){ |
| 2785 | 2842 | const char *zCode = db_column_text(&q, 0); |
| 2786 | 2843 | const char *zSub = db_column_text(&q, 2); |
| 2787 | 2844 | const char *zEmail = db_column_text(&q, 1); |
| 2788 | 2845 |
| --- 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 @@ | ||
| 551 | 551 | Web pages available to users and subscribers: |
| 552 | 552 | |
| 553 | 553 | * The [`/subscribe`](/help?cmd=/subscribe) page |
| 554 | 554 | * The [`/alerts`](/help?cmd=/alerts) page |
| 555 | 555 | * The [`/unsubscribe`](/help?cmd=/unsubscribe) page |
| 556 | + * The [`/renew`](/help?cmd=/renew) page | |
| 556 | 557 | * The [`/contact_admin`](/help?cmd=/contact_admin) page |
| 557 | 558 | |
| 558 | 559 | Administrator-only web pages: |
| 559 | 560 | |
| 560 | 561 | * The [`/setup_notification`](/help?cmd=/setup_notification) page |
| @@ -574,11 +575,11 @@ | ||
| 574 | 575 | |
| 575 | 576 | |
| 576 | 577 | <a id="datades"></a> |
| 577 | 578 | ### Data Design |
| 578 | 579 | |
| 579 | -There are three new tables in the repository database, starting with | |
| 580 | +There are two new tables in the repository database, starting with | |
| 580 | 581 | Fossil 2.7. These tables are not created in new repositories by |
| 581 | 582 | default. The tables only come into existence as needed when email |
| 582 | 583 | alerts are configured and used. |
| 583 | 584 | |
| 584 | 585 | |
| @@ -599,15 +600,14 @@ | ||
| 599 | 600 | and records timeline entries. In other words, there is one |
| 600 | 601 | row in the EVENT table for each possible timeline entry. The |
| 601 | 602 | PENDING\_ALERT table refers to EVENT table entries for which |
| 602 | 603 | we might need to send alert emails. |
| 603 | 604 | |
| 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. | |
| 609 | 609 | |
| 610 | 610 | As pointed out above, ["subscribers" are distinct from "users"](#uvs). |
| 611 | 611 | The SUBSCRIBER.SUNAME field is the optional linkage between users and |
| 612 | 612 | subscribers. |
| 613 | 613 | |
| 614 | 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 [`/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 |