Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Improved tracing capabilities for email notifications. Add the SelectAll button to the webmail display. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
f880aa82aad218ae64317f0338909da9 |
User & Date: | drh 2018-07-17 18:32:49.306 |
Context
2018-07-17
| ||
19:45 | The emailblob table holds content a little while before deleting it. Change the /test-emailblob page to /emailblob, though it is still only accessible by the administrator. ... (check-in: 15a53308 user: drh tags: trunk) | |
18:32 | Improved tracing capabilities for email notifications. Add the SelectAll button to the webmail display. ... (check-in: f880aa82 user: drh tags: trunk) | |
17:14 | Only show the SMTP transcript button if the transcript actually exists. ... (check-in: 0a6898b0 user: drh tags: trunk) | |
Changes
Changes to src/cgi.c.
︙ | ︙ | |||
342 343 344 345 346 347 348 | fflush(g.httpOut); CGIDEBUG(("DONE\n")); /* After the webpage has been sent, do any useful background ** processing. */ if( iReplyStatus==200 && fossil_strcmp(zContentType,"text/html")==0 ){ | | | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | fflush(g.httpOut); CGIDEBUG(("DONE\n")); /* After the webpage has been sent, do any useful background ** processing. */ if( iReplyStatus==200 && fossil_strcmp(zContentType,"text/html")==0 ){ email_auto_exec(0); } } /* ** Do a redirect request to the URL given in the argument. ** ** The URL must be relative to the base of the fossil server. |
︙ | ︙ |
Changes to src/email.c.
︙ | ︙ | |||
401 402 403 404 405 406 407 | SmtpSession *pSmtp; /* SMTP relay connection */ Blob out; /* For zDest=="blob" */ char *zErr; /* Error message */ u32 mFlags; /* Flags */ int bImmediateFail; /* On any error, call fossil_fatal() */ }; | | > | | 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | SmtpSession *pSmtp; /* SMTP relay connection */ Blob out; /* For zDest=="blob" */ char *zErr; /* Error message */ u32 mFlags; /* Flags */ int bImmediateFail; /* On any error, call fossil_fatal() */ }; /* Allowed values for mFlags to email_sender_new(). */ #define EMAIL_IMMEDIATE_FAIL 0x0001 /* Call fossil_fatal() on any error */ #define EMAIL_TRACE 0x0002 /* Log sending process on console */ #endif /* INTERFACE */ /* ** Shutdown an emailer. Clear all information other than the error message. */ static void emailerShutdown(EmailSender *p){ |
︙ | ︙ | |||
534 535 536 537 538 539 540 | }else if( fossil_strcmp(p->zDest, "blob")==0 ){ blob_init(&p->out, 0, 0); }else if( fossil_strcmp(p->zDest, "relay")==0 ){ const char *zRelay = 0; emailerGetSetting(p, &zRelay, "email-send-relayhost"); if( zRelay ){ u32 smtpFlags = SMTP_DIRECT; | | | 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 | }else if( fossil_strcmp(p->zDest, "blob")==0 ){ blob_init(&p->out, 0, 0); }else if( fossil_strcmp(p->zDest, "relay")==0 ){ const char *zRelay = 0; emailerGetSetting(p, &zRelay, "email-send-relayhost"); if( zRelay ){ u32 smtpFlags = SMTP_DIRECT; if( mFlags & EMAIL_TRACE ) smtpFlags |= SMTP_TRACE_STDOUT; p->pSmtp = smtp_session_new(p->zFrom, zRelay, smtpFlags); smtp_client_startup(p->pSmtp); } } return p; } |
︙ | ︙ | |||
692 693 694 695 696 697 698 699 700 701 702 703 704 705 | ** The caller maintains ownership of the input Blobs. This routine will ** read the Blobs and send them onward to the email system, but it will ** not free them. */ void email_send(EmailSender *p, Blob *pHdr, Blob *pBody){ Blob all, *pOut; u64 r1, r2; if( fossil_strcmp(p->zDest, "off")==0 ){ return; } if( fossil_strcmp(p->zDest, "blob")==0 ){ pOut = &p->out; if( blob_size(pOut) ){ blob_appendf(pOut, "%.72c\n", '='); | > > > | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 | ** The caller maintains ownership of the input Blobs. This routine will ** read the Blobs and send them onward to the email system, but it will ** not free them. */ void email_send(EmailSender *p, Blob *pHdr, Blob *pBody){ Blob all, *pOut; u64 r1, r2; if( p->mFlags & EMAIL_TRACE ){ fossil_print("Sending email\n"); } if( fossil_strcmp(p->zDest, "off")==0 ){ return; } if( fossil_strcmp(p->zDest, "blob")==0 ){ pOut = &p->out; if( blob_size(pOut) ){ blob_appendf(pOut, "%.72c\n", '='); |
︙ | ︙ | |||
941 942 943 944 945 946 947 | Blob prompt, body, hdr; const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0; int i; u32 mFlags = EMAIL_IMMEDIATE_FAIL; const char *zSubject = find_option("subject", "S", 1); const char *zSource = find_option("body", 0, 1); EmailSender *pSender; | | | 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 | Blob prompt, body, hdr; const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0; int i; u32 mFlags = EMAIL_IMMEDIATE_FAIL; const char *zSubject = find_option("subject", "S", 1); const char *zSource = find_option("body", 0, 1); EmailSender *pSender; if( find_option("smtp-trace",0,0)!=0 ) mFlags |= EMAIL_TRACE; verify_all_options(); blob_init(&prompt, 0, 0); blob_init(&body, 0, 0); blob_init(&hdr, 0, 0); blob_appendf(&hdr,"To: "); for(i=3; i<g.argc; i++){ if( i>3 ) blob_append(&hdr, ", ", 2); |
︙ | ︙ | |||
1952 1953 1954 1955 1956 1957 1958 | blob_reset(&out); db_end_transaction(0); } /* ** COMMAND: test-add-alerts ** | | > > > > > | > > > > > > > > | | 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 | blob_reset(&out); db_end_transaction(0); } /* ** COMMAND: test-add-alerts ** ** Usage: %fossil test-add-alerts [--autoexec] EVENTID ... ** ** Add one or more events to the pending_alert queue. Use this ** command during testing to force email notifications for specific ** events. ** ** EVENTIDs are text. The first character is 'c', 'w', or 't' ** for check-in, wiki, or ticket. The remaining text is a ** integer that references the EVENT.OBJID value for the event. ** Run /timeline?showid to see these OBJID values. ** ** If the --autoexec option is included, then email_auto_exec() is run ** after all alerts have been added. This will cause the alerts to ** be sent out with the SENDALERT_TRACE option. */ void test_add_alert_cmd(void){ int i; int doAuto = find_option("autoexec",0,0)!=0; db_find_and_open_repository(0, 0); verify_all_options(); db_begin_write(); email_schema(0); for(i=2; i<g.argc; i++){ db_multi_exec("REPLACE INTO pending_alert(eventId) VALUES(%Q)", g.argv[i]); } db_end_transaction(0); if( doAuto ){ email_auto_exec(SENDALERT_TRACE); } } #if INTERFACE /* ** Flags for email_send_alerts() */ #define SENDALERT_DIGEST 0x0001 /* Send a digest */ #define SENDALERT_PRESERVE 0x0002 /* Do not mark the task as done */ #define SENDALERT_STDOUT 0x0004 /* Print emails instead of sending */ #define SENDALERT_TRACE 0x0008 /* Trace operation for debugging */ #endif /* INTERFACE */ /* ** Send alert emails to all subscribers. */ void email_send_alerts(u32 flags){ EmailEvent *pEvents, *p; int nEvent = 0; Stmt q; const char *zDigest = "false"; Blob hdr, body; const char *zUrl; const char *zRepoName; const char *zFrom; const char *zDest = (flags & SENDALERT_STDOUT) ? "stdout" : 0; EmailSender *pSender = 0; u32 senderFlags = 0; if( g.fSqlTrace ) fossil_trace("-- BEGIN email_send_alerts(%u)\n", flags); db_begin_transaction(); if( !email_enabled() ) goto send_alerts_done; zUrl = db_get("email-url",0); if( zUrl==0 ) goto send_alerts_done; zRepoName = db_get("email-subname",0); if( zRepoName==0 ) goto send_alerts_done; zFrom = db_get("email-self",0); if( zFrom==0 ) goto send_alerts_done; if( flags & SENDALERT_TRACE ){ senderFlags |= EMAIL_TRACE; } pSender = email_sender_new(zDest, senderFlags); db_multi_exec( "DROP TABLE IF EXISTS temp.wantalert;" "CREATE TEMP TABLE wantalert(eventId TEXT);" ); if( flags & SENDALERT_DIGEST ){ db_multi_exec( "INSERT INTO wantalert SELECT eventid FROM pending_alert" |
︙ | ︙ | |||
2091 2092 2093 2094 2095 2096 2097 2098 | /* ** Check to see if any email notifications need to occur, and then ** do them. ** ** This routine is called after certain webpages have been run and ** have already responded. */ | > > > > | | | | 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 | /* ** Check to see if any email notifications need to occur, and then ** do them. ** ** This routine is called after certain webpages have been run and ** have already responded. ** ** The mFlags option is zero or more of the SENDALERT_* flags. Normally ** this flag is zero, but the test-set-alert command sets it to ** SENDALERT_TRACE. */ void email_auto_exec(u32 mFlags){ int iJulianDay; if( g.db==0 ) return; if( db_transaction_nesting_depth()!=0 ){ fossil_warning("Called email_auto_exec() from within transaction " "started at %z", db_transaction_start_point()); return; } if( !email_tables_exist() ) return; if( !db_get_boolean("email-autoexec",0) ) return; db_begin_write(); email_send_alerts(mFlags); iJulianDay = db_int(0, "SELECT julianday('now')"); if( iJulianDay>db_get_int("email-last-digest",0) ){ if( db_transaction_nesting_depth()!=1 ){ fossil_warning("Transaction nesting error prior to digest processing"); }else{ db_set_int("email-last-digest",iJulianDay,0); email_send_alerts(SENDALERT_DIGEST|mFlags); } } db_commit_transaction(); } /* ** WEBPAGE: contact_admin |
︙ | ︙ |
Changes to src/smtp.c.
︙ | ︙ | |||
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 | db_step(&s); db_reset(&s); p->idTranscript = db_last_insert_rowid(); db_multi_exec( "UPDATE emailblob SET enref=%d WHERE emailid=%lld", p->nEts, p->idTranscript); } } db_bind_int64(&s, ":ets", p->idTranscript); db_bind_str(&s, ":etxt", &p->msg); db_step(&s); db_finalize(&s); p->idMsg = db_last_insert_rowid(); | > > | 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 | db_step(&s); db_reset(&s); p->idTranscript = db_last_insert_rowid(); db_multi_exec( "UPDATE emailblob SET enref=%d WHERE emailid=%lld", p->nEts, p->idTranscript); } smtp_server_send(p, "221-Transcript id %lld nref %d\r\n", p->idTranscript, p->nEts); } db_bind_int64(&s, ":ets", p->idTranscript); db_bind_str(&s, ":etxt", &p->msg); db_step(&s); db_finalize(&s); p->idMsg = db_last_insert_rowid(); |
︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 | } smtp_server_send(&x, "354 ready\r\n"); smtp_server_prepend_header_lines(&x); smtp_server_capture_data(&x, z, sizeof(z)); smtp_server_send(&x, "250 ok\r\n"); }else if( strncmp(z, "QUIT", 4)==0 && fossil_isspace(z[4]) ){ | < > | 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 | } smtp_server_send(&x, "354 ready\r\n"); smtp_server_prepend_header_lines(&x); smtp_server_capture_data(&x, z, sizeof(z)); smtp_server_send(&x, "250 ok\r\n"); }else if( strncmp(z, "QUIT", 4)==0 && fossil_isspace(z[4]) ){ smtp_server_route_incoming(&x, 1); smtp_server_send(&x, "221 closing connection\r\n"); break; }else { smtp_server_send(&x, "500 unknown command\r\n"); } } smtp_server_clear(&x, SMTPSRV_CLEAR_ALL); } |
Changes to src/webmail.c.
︙ | ︙ | |||
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 | }else{ @ <input type="submit" name="trash", value="Delete"> if( d!=1 ){ @ <input type="submit" name="unread" value="Mark as unread"> } @ <input type="submit" name="read" value="Mark as read"> } @ <a href="%s(url_render(&url,0,0,0,0))">refresh</a> @ </td><td align="right"> if( pg>0 ){ sqlite3_snprintf(sizeof(zPPg), zPPg, "%d", pg-1); @ <a href="%s(url_render(&url,"pg",zPPg,0,0))">< Newer</a> } if( got>50 ){ sqlite3_snprintf(sizeof(zNPg),zNPg,"%d",pg+1); @ <a href="%s(url_render(&url,"pg",zNPg,0,0))">Older ></a></td> } @ </table> @ <table> while( db_step(&q)==SQLITE_ROW ){ const char *zId = db_column_text(&q,0); const char *zFrom = db_column_text(&q, 1); const char *zDate = db_column_text(&q, 2); const char *zSubject = db_column_text(&q, 4); @ <tr> | > | > > > > > > > > | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 | }else{ @ <input type="submit" name="trash", value="Delete"> if( d!=1 ){ @ <input type="submit" name="unread" value="Mark as unread"> } @ <input type="submit" name="read" value="Mark as read"> } @ <button onclick="webmailSelectAll(); return false;">Select All</button> @ <a href="%s(url_render(&url,0,0,0,0))">refresh</a> @ </td><td align="right"> if( pg>0 ){ sqlite3_snprintf(sizeof(zPPg), zPPg, "%d", pg-1); @ <a href="%s(url_render(&url,"pg",zPPg,0,0))">< Newer</a> } if( got>50 ){ sqlite3_snprintf(sizeof(zNPg),zNPg,"%d",pg+1); @ <a href="%s(url_render(&url,"pg",zNPg,0,0))">Older ></a></td> } @ </table> @ <table> while( db_step(&q)==SQLITE_ROW ){ const char *zId = db_column_text(&q,0); const char *zFrom = db_column_text(&q, 1); const char *zDate = db_column_text(&q, 2); const char *zSubject = db_column_text(&q, 4); @ <tr> @ <td><input type="checkbox" class="webmailckbox" name="e%s(zId)"></td> @ <td>%h(zFrom)</td> @ <td><a href="%s(url_render(&url,"id",zId,0,0))">%h(zSubject)</a> \ @ %s(zDate)</td> if( showAll ){ const char *zTo = db_column_text(&q,5); @ <td><a href="%s(url_render(&url,"user",zTo,0,0))">%h(zTo)</a></td> } @ </tr> } db_finalize(&q); @ </table> @ </form> style_footer(); @ <script> @ function webmailSelectAll(){ @ var x = document.getElementsByClassName("webmailckbox"); @ for(i=0; i<x.length; i++){ @ x[i].checked = true; @ } @ } @ </script> db_end_transaction(0); } /* ** WEBPAGE: test-emailblob ** ** This page, accessible only to administrators, allows easy viewing of |
︙ | ︙ |