Fossil SCM
Rearrange some of the subcommands on "fossil alerts" for better UX. Fix a problem in the /webmail display for messages with no subject. Improved comments.
Commit
81c254311e5b812bc392b413990e0a745c83f3d6fb014c536b828e939bd382ab
Parent
efbd6caa7c9d2c1…
2 files changed
+88
-64
+2
-1
+88
-64
| --- src/email.c | ||
| +++ src/email.c | ||
| @@ -806,42 +806,42 @@ | ||
| 806 | 806 | ** |
| 807 | 807 | ** Usage: %fossil alerts SUBCOMMAND ARGS... |
| 808 | 808 | ** |
| 809 | 809 | ** Subcommands: |
| 810 | 810 | ** |
| 811 | -** exec Compose and send pending email alerts. | |
| 811 | +** pending Show all pending alerts. Useful for debugging. | |
| 812 | +** | |
| 813 | +** reset Hard reset of all email notification tables | |
| 814 | +** in the repository. This erases all subscription | |
| 815 | +** information. ** Use with extreme care ** | |
| 816 | +** | |
| 817 | +** send Compose and send pending email alerts. | |
| 812 | 818 | ** Some installations may want to do this via |
| 813 | 819 | ** a cron-job to make sure alerts are sent |
| 814 | 820 | ** in a timely manner. |
| 815 | 821 | ** Options: |
| 816 | 822 | ** |
| 817 | 823 | ** --digest Send digests |
| 818 | -** --test Resets to standard output | |
| 819 | -** | |
| 820 | -** pending Show all pending alerts. Useful for debugging. | |
| 821 | -** | |
| 822 | -** reset Hard reset of all email notification tables | |
| 823 | -** in the repository. This erases all subscription | |
| 824 | -** information. Use with extreme care. | |
| 825 | -** | |
| 826 | -** send TO [OPTIONS] Send a single email message using whatever | |
| 827 | -** email sending mechanism is currently configured. | |
| 828 | -** Use this for testing the email configuration. | |
| 829 | -** Options: | |
| 830 | -** | |
| 831 | -** --body FILENAME | |
| 832 | -** --smtp-trace | |
| 833 | -** --stdout | |
| 834 | -** --subject|-S SUBJECT | |
| 824 | +** --test Write to standard output | |
| 835 | 825 | ** |
| 836 | 826 | ** settings [NAME VALUE] With no arguments, list all email settings. |
| 837 | 827 | ** Or change the value of a single email setting. |
| 838 | 828 | ** |
| 839 | 829 | ** status Report on the status of the email alert |
| 840 | 830 | ** subsystem |
| 841 | 831 | ** |
| 842 | 832 | ** subscribers [PATTERN] List all subscribers matching PATTERN. |
| 833 | +** | |
| 834 | +** test-message TO [OPTS] Send a single email message using whatever | |
| 835 | +** email sending mechanism is currently configured. | |
| 836 | +** Use this for testing the email notification | |
| 837 | +** configuration. Options: | |
| 838 | +** | |
| 839 | +** --body FILENAME | |
| 840 | +** --smtp-trace | |
| 841 | +** --stdout | |
| 842 | +** --subject|-S SUBJECT | |
| 843 | 843 | ** |
| 844 | 844 | ** unsubscribe EMAIL Remove a single subscriber with the given EMAIL. |
| 845 | 845 | */ |
| 846 | 846 | void email_cmd(void){ |
| 847 | 847 | const char *zCmd; |
| @@ -848,19 +848,10 @@ | ||
| 848 | 848 | int nCmd; |
| 849 | 849 | db_find_and_open_repository(0, 0); |
| 850 | 850 | email_schema(0); |
| 851 | 851 | zCmd = g.argc>=3 ? g.argv[2] : "x"; |
| 852 | 852 | nCmd = (int)strlen(zCmd); |
| 853 | - if( strncmp(zCmd, "exec", nCmd)==0 ){ | |
| 854 | - u32 eFlags = 0; | |
| 855 | - if( find_option("digest",0,0)!=0 ) eFlags |= SENDALERT_DIGEST; | |
| 856 | - if( find_option("test",0,0)!=0 ){ | |
| 857 | - eFlags |= SENDALERT_PRESERVE|SENDALERT_STDOUT; | |
| 858 | - } | |
| 859 | - verify_all_options(); | |
| 860 | - email_send_alerts(eFlags); | |
| 861 | - }else | |
| 862 | 853 | if( strncmp(zCmd, "pending", nCmd)==0 ){ |
| 863 | 854 | Stmt q; |
| 864 | 855 | verify_all_options(); |
| 865 | 856 | if( g.argc!=3 ) usage("pending"); |
| 866 | 857 | db_prepare(&q,"SELECT eventid, sentSep, sentDigest, sentMod" |
| @@ -902,43 +893,17 @@ | ||
| 902 | 893 | ); |
| 903 | 894 | email_schema(0); |
| 904 | 895 | } |
| 905 | 896 | }else |
| 906 | 897 | if( strncmp(zCmd, "send", nCmd)==0 ){ |
| 907 | - Blob prompt, body, hdr; | |
| 908 | - const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0; | |
| 909 | - int i; | |
| 910 | - u32 mFlags = EMAIL_IMMEDIATE_FAIL; | |
| 911 | - const char *zSubject = find_option("subject", "S", 1); | |
| 912 | - const char *zSource = find_option("body", 0, 1); | |
| 913 | - EmailSender *pSender; | |
| 914 | - if( find_option("smtp-trace",0,0)!=0 ) mFlags |= EMAIL_TRACE; | |
| 898 | + u32 eFlags = 0; | |
| 899 | + if( find_option("digest",0,0)!=0 ) eFlags |= SENDALERT_DIGEST; | |
| 900 | + if( find_option("test",0,0)!=0 ){ | |
| 901 | + eFlags |= SENDALERT_PRESERVE|SENDALERT_STDOUT; | |
| 902 | + } | |
| 915 | 903 | verify_all_options(); |
| 916 | - blob_init(&prompt, 0, 0); | |
| 917 | - blob_init(&body, 0, 0); | |
| 918 | - blob_init(&hdr, 0, 0); | |
| 919 | - blob_appendf(&hdr,"To: "); | |
| 920 | - for(i=3; i<g.argc; i++){ | |
| 921 | - if( i>3 ) blob_append(&hdr, ", ", 2); | |
| 922 | - blob_appendf(&hdr, "<%s>", g.argv[i]); | |
| 923 | - } | |
| 924 | - blob_append(&hdr,"\r\n",2); | |
| 925 | - if( zSubject ){ | |
| 926 | - blob_appendf(&hdr, "Subject: %s\r\n", zSubject); | |
| 927 | - } | |
| 928 | - if( zSource ){ | |
| 929 | - blob_read_from_file(&body, zSource, ExtFILE); | |
| 930 | - }else{ | |
| 931 | - prompt_for_user_comment(&body, &prompt); | |
| 932 | - } | |
| 933 | - blob_add_final_newline(&body); | |
| 934 | - pSender = email_sender_new(zDest, mFlags); | |
| 935 | - email_send(pSender, &hdr, &body); | |
| 936 | - email_sender_free(pSender); | |
| 937 | - blob_reset(&hdr); | |
| 938 | - blob_reset(&body); | |
| 939 | - blob_reset(&prompt); | |
| 904 | + email_send_alerts(eFlags); | |
| 940 | 905 | }else |
| 941 | 906 | if( strncmp(zCmd, "settings", nCmd)==0 ){ |
| 942 | 907 | int isGlobal = find_option("global",0,0)!=0; |
| 943 | 908 | int nSetting; |
| 944 | 909 | const Setting *pSetting = setting_info(&nSetting); |
| @@ -959,11 +924,10 @@ | ||
| 959 | 924 | if( strncmp(pSetting->name,"email-",6)!=0 ) continue; |
| 960 | 925 | print_setting(pSetting); |
| 961 | 926 | } |
| 962 | 927 | }else |
| 963 | 928 | if( strncmp(zCmd, "status", nCmd)==0 ){ |
| 964 | - int isGlobal = find_option("global",0,0)!=0; | |
| 965 | 929 | int nSetting, n; |
| 966 | 930 | static const char *zFmt = "%-29s %d\n"; |
| 967 | 931 | const Setting *pSetting = setting_info(&nSetting); |
| 968 | 932 | db_open_config(1, 0); |
| 969 | 933 | verify_all_options(); |
| @@ -1002,19 +966,55 @@ | ||
| 1002 | 966 | } |
| 1003 | 967 | while( db_step(&q)==SQLITE_ROW ){ |
| 1004 | 968 | fossil_print("%s\n", db_column_text(&q, 0)); |
| 1005 | 969 | } |
| 1006 | 970 | db_finalize(&q); |
| 971 | + }else | |
| 972 | + if( strncmp(zCmd, "test-message", nCmd)==0 ){ | |
| 973 | + Blob prompt, body, hdr; | |
| 974 | + const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0; | |
| 975 | + int i; | |
| 976 | + u32 mFlags = EMAIL_IMMEDIATE_FAIL; | |
| 977 | + const char *zSubject = find_option("subject", "S", 1); | |
| 978 | + const char *zSource = find_option("body", 0, 1); | |
| 979 | + EmailSender *pSender; | |
| 980 | + if( find_option("smtp-trace",0,0)!=0 ) mFlags |= EMAIL_TRACE; | |
| 981 | + verify_all_options(); | |
| 982 | + blob_init(&prompt, 0, 0); | |
| 983 | + blob_init(&body, 0, 0); | |
| 984 | + blob_init(&hdr, 0, 0); | |
| 985 | + blob_appendf(&hdr,"To: "); | |
| 986 | + for(i=3; i<g.argc; i++){ | |
| 987 | + if( i>3 ) blob_append(&hdr, ", ", 2); | |
| 988 | + blob_appendf(&hdr, "<%s>", g.argv[i]); | |
| 989 | + } | |
| 990 | + blob_append(&hdr,"\r\n",2); | |
| 991 | + if( zSubject ){ | |
| 992 | + blob_appendf(&hdr, "Subject: %s\r\n", zSubject); | |
| 993 | + } | |
| 994 | + if( zSource ){ | |
| 995 | + blob_read_from_file(&body, zSource, ExtFILE); | |
| 996 | + }else{ | |
| 997 | + prompt_for_user_comment(&body, &prompt); | |
| 998 | + } | |
| 999 | + blob_add_final_newline(&body); | |
| 1000 | + pSender = email_sender_new(zDest, mFlags); | |
| 1001 | + email_send(pSender, &hdr, &body); | |
| 1002 | + email_sender_free(pSender); | |
| 1003 | + blob_reset(&hdr); | |
| 1004 | + blob_reset(&body); | |
| 1005 | + blob_reset(&prompt); | |
| 1007 | 1006 | }else |
| 1008 | 1007 | if( strncmp(zCmd, "unsubscribe", nCmd)==0 ){ |
| 1009 | 1008 | verify_all_options(); |
| 1010 | 1009 | if( g.argc!=4 ) usage("unsubscribe EMAIL"); |
| 1011 | 1010 | db_multi_exec( |
| 1012 | 1011 | "DELETE FROM subscriber WHERE semail=%Q", g.argv[3]); |
| 1013 | 1012 | }else |
| 1014 | 1013 | { |
| 1015 | - usage("exec|pending|reset|send|setting|status|subscribers|unsubscribe"); | |
| 1014 | + usage("pending|reset|send|setting|status|" | |
| 1015 | + "subscribers|test-message|unsubscribe"); | |
| 1016 | 1016 | } |
| 1017 | 1017 | } |
| 1018 | 1018 | |
| 1019 | 1019 | /* |
| 1020 | 1020 | ** Do error checking on a submitted subscription form. Return TRUE |
| @@ -1971,12 +1971,12 @@ | ||
| 1971 | 1971 | ** |
| 1972 | 1972 | ** Add one or more events to the pending_alert queue. Use this |
| 1973 | 1973 | ** command during testing to force email notifications for specific |
| 1974 | 1974 | ** events. |
| 1975 | 1975 | ** |
| 1976 | -** EVENTIDs are text. The first character is 'c', 'w', or 't' | |
| 1977 | -** for check-in, wiki, or ticket. The remaining text is a | |
| 1976 | +** EVENTIDs are text. The first character is 'c', 'f', 't', or 'w' | |
| 1977 | +** for check-in, forum, ticket, or wiki. The remaining text is a | |
| 1978 | 1978 | ** integer that references the EVENT.OBJID value for the event. |
| 1979 | 1979 | ** Run /timeline?showid to see these OBJID values. |
| 1980 | 1980 | ** |
| 1981 | 1981 | ** If the --backoffice option is included, then email_backoffice() is run |
| 1982 | 1982 | ** after all alerts have been added. This will cause the alerts to |
| @@ -2008,11 +2008,35 @@ | ||
| 2008 | 2008 | #define SENDALERT_TRACE 0x0008 /* Trace operation for debugging */ |
| 2009 | 2009 | |
| 2010 | 2010 | #endif /* INTERFACE */ |
| 2011 | 2011 | |
| 2012 | 2012 | /* |
| 2013 | -** Send alert emails to all subscribers. | |
| 2013 | +** Send alert emails to subscribers. | |
| 2014 | +** | |
| 2015 | +** This procedure is run by either the backoffice, or in response to the | |
| 2016 | +** "fossil alerts send" command. Details of operation are controlled by | |
| 2017 | +** the flags parameter. | |
| 2018 | +** | |
| 2019 | +** Here is a summary of what happens: | |
| 2020 | +** | |
| 2021 | +** (1) Create a TEMP table wantalert(eventId,needMod) and fill it with | |
| 2022 | +** all the events that we want to send alerts about. The needMod | |
| 2023 | +** flags is set if and only if the event is still awaiting | |
| 2024 | +** moderator approval. Events with the needMod flag are only | |
| 2025 | +** shown to users that have moderator privileges. | |
| 2026 | +** | |
| 2027 | +** (2) Call email_compute_event_text() to compute a list of EmailEvent | |
| 2028 | +** objects that describe all events about which we want to send | |
| 2029 | +** alerts. | |
| 2030 | +** | |
| 2031 | +** (3) Loop over all subscribers. Compose and send one or more email | |
| 2032 | +** messages to each subscriber that describe the events for | |
| 2033 | +** which the subscriber has expressed interest and has | |
| 2034 | +** appropriate privileges. | |
| 2035 | +** | |
| 2036 | +** (4) Update the pending_alerts table to indicate that alerts have been | |
| 2037 | +** sent. | |
| 2014 | 2038 | */ |
| 2015 | 2039 | void email_send_alerts(u32 flags){ |
| 2016 | 2040 | EmailEvent *pEvents, *p; |
| 2017 | 2041 | int nEvent = 0; |
| 2018 | 2042 | Stmt q; |
| 2019 | 2043 |
| --- src/email.c | |
| +++ src/email.c | |
| @@ -806,42 +806,42 @@ | |
| 806 | ** |
| 807 | ** Usage: %fossil alerts SUBCOMMAND ARGS... |
| 808 | ** |
| 809 | ** Subcommands: |
| 810 | ** |
| 811 | ** exec Compose and send pending email alerts. |
| 812 | ** Some installations may want to do this via |
| 813 | ** a cron-job to make sure alerts are sent |
| 814 | ** in a timely manner. |
| 815 | ** Options: |
| 816 | ** |
| 817 | ** --digest Send digests |
| 818 | ** --test Resets to standard output |
| 819 | ** |
| 820 | ** pending Show all pending alerts. Useful for debugging. |
| 821 | ** |
| 822 | ** reset Hard reset of all email notification tables |
| 823 | ** in the repository. This erases all subscription |
| 824 | ** information. Use with extreme care. |
| 825 | ** |
| 826 | ** send TO [OPTIONS] Send a single email message using whatever |
| 827 | ** email sending mechanism is currently configured. |
| 828 | ** Use this for testing the email configuration. |
| 829 | ** Options: |
| 830 | ** |
| 831 | ** --body FILENAME |
| 832 | ** --smtp-trace |
| 833 | ** --stdout |
| 834 | ** --subject|-S SUBJECT |
| 835 | ** |
| 836 | ** settings [NAME VALUE] With no arguments, list all email settings. |
| 837 | ** Or change the value of a single email setting. |
| 838 | ** |
| 839 | ** status Report on the status of the email alert |
| 840 | ** subsystem |
| 841 | ** |
| 842 | ** subscribers [PATTERN] List all subscribers matching PATTERN. |
| 843 | ** |
| 844 | ** unsubscribe EMAIL Remove a single subscriber with the given EMAIL. |
| 845 | */ |
| 846 | void email_cmd(void){ |
| 847 | const char *zCmd; |
| @@ -848,19 +848,10 @@ | |
| 848 | int nCmd; |
| 849 | db_find_and_open_repository(0, 0); |
| 850 | email_schema(0); |
| 851 | zCmd = g.argc>=3 ? g.argv[2] : "x"; |
| 852 | nCmd = (int)strlen(zCmd); |
| 853 | if( strncmp(zCmd, "exec", nCmd)==0 ){ |
| 854 | u32 eFlags = 0; |
| 855 | if( find_option("digest",0,0)!=0 ) eFlags |= SENDALERT_DIGEST; |
| 856 | if( find_option("test",0,0)!=0 ){ |
| 857 | eFlags |= SENDALERT_PRESERVE|SENDALERT_STDOUT; |
| 858 | } |
| 859 | verify_all_options(); |
| 860 | email_send_alerts(eFlags); |
| 861 | }else |
| 862 | if( strncmp(zCmd, "pending", nCmd)==0 ){ |
| 863 | Stmt q; |
| 864 | verify_all_options(); |
| 865 | if( g.argc!=3 ) usage("pending"); |
| 866 | db_prepare(&q,"SELECT eventid, sentSep, sentDigest, sentMod" |
| @@ -902,43 +893,17 @@ | |
| 902 | ); |
| 903 | email_schema(0); |
| 904 | } |
| 905 | }else |
| 906 | if( strncmp(zCmd, "send", nCmd)==0 ){ |
| 907 | Blob prompt, body, hdr; |
| 908 | const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0; |
| 909 | int i; |
| 910 | u32 mFlags = EMAIL_IMMEDIATE_FAIL; |
| 911 | const char *zSubject = find_option("subject", "S", 1); |
| 912 | const char *zSource = find_option("body", 0, 1); |
| 913 | EmailSender *pSender; |
| 914 | if( find_option("smtp-trace",0,0)!=0 ) mFlags |= EMAIL_TRACE; |
| 915 | verify_all_options(); |
| 916 | blob_init(&prompt, 0, 0); |
| 917 | blob_init(&body, 0, 0); |
| 918 | blob_init(&hdr, 0, 0); |
| 919 | blob_appendf(&hdr,"To: "); |
| 920 | for(i=3; i<g.argc; i++){ |
| 921 | if( i>3 ) blob_append(&hdr, ", ", 2); |
| 922 | blob_appendf(&hdr, "<%s>", g.argv[i]); |
| 923 | } |
| 924 | blob_append(&hdr,"\r\n",2); |
| 925 | if( zSubject ){ |
| 926 | blob_appendf(&hdr, "Subject: %s\r\n", zSubject); |
| 927 | } |
| 928 | if( zSource ){ |
| 929 | blob_read_from_file(&body, zSource, ExtFILE); |
| 930 | }else{ |
| 931 | prompt_for_user_comment(&body, &prompt); |
| 932 | } |
| 933 | blob_add_final_newline(&body); |
| 934 | pSender = email_sender_new(zDest, mFlags); |
| 935 | email_send(pSender, &hdr, &body); |
| 936 | email_sender_free(pSender); |
| 937 | blob_reset(&hdr); |
| 938 | blob_reset(&body); |
| 939 | blob_reset(&prompt); |
| 940 | }else |
| 941 | if( strncmp(zCmd, "settings", nCmd)==0 ){ |
| 942 | int isGlobal = find_option("global",0,0)!=0; |
| 943 | int nSetting; |
| 944 | const Setting *pSetting = setting_info(&nSetting); |
| @@ -959,11 +924,10 @@ | |
| 959 | if( strncmp(pSetting->name,"email-",6)!=0 ) continue; |
| 960 | print_setting(pSetting); |
| 961 | } |
| 962 | }else |
| 963 | if( strncmp(zCmd, "status", nCmd)==0 ){ |
| 964 | int isGlobal = find_option("global",0,0)!=0; |
| 965 | int nSetting, n; |
| 966 | static const char *zFmt = "%-29s %d\n"; |
| 967 | const Setting *pSetting = setting_info(&nSetting); |
| 968 | db_open_config(1, 0); |
| 969 | verify_all_options(); |
| @@ -1002,19 +966,55 @@ | |
| 1002 | } |
| 1003 | while( db_step(&q)==SQLITE_ROW ){ |
| 1004 | fossil_print("%s\n", db_column_text(&q, 0)); |
| 1005 | } |
| 1006 | db_finalize(&q); |
| 1007 | }else |
| 1008 | if( strncmp(zCmd, "unsubscribe", nCmd)==0 ){ |
| 1009 | verify_all_options(); |
| 1010 | if( g.argc!=4 ) usage("unsubscribe EMAIL"); |
| 1011 | db_multi_exec( |
| 1012 | "DELETE FROM subscriber WHERE semail=%Q", g.argv[3]); |
| 1013 | }else |
| 1014 | { |
| 1015 | usage("exec|pending|reset|send|setting|status|subscribers|unsubscribe"); |
| 1016 | } |
| 1017 | } |
| 1018 | |
| 1019 | /* |
| 1020 | ** Do error checking on a submitted subscription form. Return TRUE |
| @@ -1971,12 +1971,12 @@ | |
| 1971 | ** |
| 1972 | ** Add one or more events to the pending_alert queue. Use this |
| 1973 | ** command during testing to force email notifications for specific |
| 1974 | ** events. |
| 1975 | ** |
| 1976 | ** EVENTIDs are text. The first character is 'c', 'w', or 't' |
| 1977 | ** for check-in, wiki, or ticket. The remaining text is a |
| 1978 | ** integer that references the EVENT.OBJID value for the event. |
| 1979 | ** Run /timeline?showid to see these OBJID values. |
| 1980 | ** |
| 1981 | ** If the --backoffice option is included, then email_backoffice() is run |
| 1982 | ** after all alerts have been added. This will cause the alerts to |
| @@ -2008,11 +2008,35 @@ | |
| 2008 | #define SENDALERT_TRACE 0x0008 /* Trace operation for debugging */ |
| 2009 | |
| 2010 | #endif /* INTERFACE */ |
| 2011 | |
| 2012 | /* |
| 2013 | ** Send alert emails to all subscribers. |
| 2014 | */ |
| 2015 | void email_send_alerts(u32 flags){ |
| 2016 | EmailEvent *pEvents, *p; |
| 2017 | int nEvent = 0; |
| 2018 | Stmt q; |
| 2019 |
| --- src/email.c | |
| +++ src/email.c | |
| @@ -806,42 +806,42 @@ | |
| 806 | ** |
| 807 | ** Usage: %fossil alerts SUBCOMMAND ARGS... |
| 808 | ** |
| 809 | ** Subcommands: |
| 810 | ** |
| 811 | ** pending Show all pending alerts. Useful for debugging. |
| 812 | ** |
| 813 | ** reset Hard reset of all email notification tables |
| 814 | ** in the repository. This erases all subscription |
| 815 | ** information. ** Use with extreme care ** |
| 816 | ** |
| 817 | ** send Compose and send pending email alerts. |
| 818 | ** Some installations may want to do this via |
| 819 | ** a cron-job to make sure alerts are sent |
| 820 | ** in a timely manner. |
| 821 | ** Options: |
| 822 | ** |
| 823 | ** --digest Send digests |
| 824 | ** --test Write to standard output |
| 825 | ** |
| 826 | ** settings [NAME VALUE] With no arguments, list all email settings. |
| 827 | ** Or change the value of a single email setting. |
| 828 | ** |
| 829 | ** status Report on the status of the email alert |
| 830 | ** subsystem |
| 831 | ** |
| 832 | ** subscribers [PATTERN] List all subscribers matching PATTERN. |
| 833 | ** |
| 834 | ** test-message TO [OPTS] Send a single email message using whatever |
| 835 | ** email sending mechanism is currently configured. |
| 836 | ** Use this for testing the email notification |
| 837 | ** configuration. Options: |
| 838 | ** |
| 839 | ** --body FILENAME |
| 840 | ** --smtp-trace |
| 841 | ** --stdout |
| 842 | ** --subject|-S SUBJECT |
| 843 | ** |
| 844 | ** unsubscribe EMAIL Remove a single subscriber with the given EMAIL. |
| 845 | */ |
| 846 | void email_cmd(void){ |
| 847 | const char *zCmd; |
| @@ -848,19 +848,10 @@ | |
| 848 | int nCmd; |
| 849 | db_find_and_open_repository(0, 0); |
| 850 | email_schema(0); |
| 851 | zCmd = g.argc>=3 ? g.argv[2] : "x"; |
| 852 | nCmd = (int)strlen(zCmd); |
| 853 | if( strncmp(zCmd, "pending", nCmd)==0 ){ |
| 854 | Stmt q; |
| 855 | verify_all_options(); |
| 856 | if( g.argc!=3 ) usage("pending"); |
| 857 | db_prepare(&q,"SELECT eventid, sentSep, sentDigest, sentMod" |
| @@ -902,43 +893,17 @@ | |
| 893 | ); |
| 894 | email_schema(0); |
| 895 | } |
| 896 | }else |
| 897 | if( strncmp(zCmd, "send", nCmd)==0 ){ |
| 898 | u32 eFlags = 0; |
| 899 | if( find_option("digest",0,0)!=0 ) eFlags |= SENDALERT_DIGEST; |
| 900 | if( find_option("test",0,0)!=0 ){ |
| 901 | eFlags |= SENDALERT_PRESERVE|SENDALERT_STDOUT; |
| 902 | } |
| 903 | verify_all_options(); |
| 904 | email_send_alerts(eFlags); |
| 905 | }else |
| 906 | if( strncmp(zCmd, "settings", nCmd)==0 ){ |
| 907 | int isGlobal = find_option("global",0,0)!=0; |
| 908 | int nSetting; |
| 909 | const Setting *pSetting = setting_info(&nSetting); |
| @@ -959,11 +924,10 @@ | |
| 924 | if( strncmp(pSetting->name,"email-",6)!=0 ) continue; |
| 925 | print_setting(pSetting); |
| 926 | } |
| 927 | }else |
| 928 | if( strncmp(zCmd, "status", nCmd)==0 ){ |
| 929 | int nSetting, n; |
| 930 | static const char *zFmt = "%-29s %d\n"; |
| 931 | const Setting *pSetting = setting_info(&nSetting); |
| 932 | db_open_config(1, 0); |
| 933 | verify_all_options(); |
| @@ -1002,19 +966,55 @@ | |
| 966 | } |
| 967 | while( db_step(&q)==SQLITE_ROW ){ |
| 968 | fossil_print("%s\n", db_column_text(&q, 0)); |
| 969 | } |
| 970 | db_finalize(&q); |
| 971 | }else |
| 972 | if( strncmp(zCmd, "test-message", nCmd)==0 ){ |
| 973 | Blob prompt, body, hdr; |
| 974 | const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0; |
| 975 | int i; |
| 976 | u32 mFlags = EMAIL_IMMEDIATE_FAIL; |
| 977 | const char *zSubject = find_option("subject", "S", 1); |
| 978 | const char *zSource = find_option("body", 0, 1); |
| 979 | EmailSender *pSender; |
| 980 | if( find_option("smtp-trace",0,0)!=0 ) mFlags |= EMAIL_TRACE; |
| 981 | verify_all_options(); |
| 982 | blob_init(&prompt, 0, 0); |
| 983 | blob_init(&body, 0, 0); |
| 984 | blob_init(&hdr, 0, 0); |
| 985 | blob_appendf(&hdr,"To: "); |
| 986 | for(i=3; i<g.argc; i++){ |
| 987 | if( i>3 ) blob_append(&hdr, ", ", 2); |
| 988 | blob_appendf(&hdr, "<%s>", g.argv[i]); |
| 989 | } |
| 990 | blob_append(&hdr,"\r\n",2); |
| 991 | if( zSubject ){ |
| 992 | blob_appendf(&hdr, "Subject: %s\r\n", zSubject); |
| 993 | } |
| 994 | if( zSource ){ |
| 995 | blob_read_from_file(&body, zSource, ExtFILE); |
| 996 | }else{ |
| 997 | prompt_for_user_comment(&body, &prompt); |
| 998 | } |
| 999 | blob_add_final_newline(&body); |
| 1000 | pSender = email_sender_new(zDest, mFlags); |
| 1001 | email_send(pSender, &hdr, &body); |
| 1002 | email_sender_free(pSender); |
| 1003 | blob_reset(&hdr); |
| 1004 | blob_reset(&body); |
| 1005 | blob_reset(&prompt); |
| 1006 | }else |
| 1007 | if( strncmp(zCmd, "unsubscribe", nCmd)==0 ){ |
| 1008 | verify_all_options(); |
| 1009 | if( g.argc!=4 ) usage("unsubscribe EMAIL"); |
| 1010 | db_multi_exec( |
| 1011 | "DELETE FROM subscriber WHERE semail=%Q", g.argv[3]); |
| 1012 | }else |
| 1013 | { |
| 1014 | usage("pending|reset|send|setting|status|" |
| 1015 | "subscribers|test-message|unsubscribe"); |
| 1016 | } |
| 1017 | } |
| 1018 | |
| 1019 | /* |
| 1020 | ** Do error checking on a submitted subscription form. Return TRUE |
| @@ -1971,12 +1971,12 @@ | |
| 1971 | ** |
| 1972 | ** Add one or more events to the pending_alert queue. Use this |
| 1973 | ** command during testing to force email notifications for specific |
| 1974 | ** events. |
| 1975 | ** |
| 1976 | ** EVENTIDs are text. The first character is 'c', 'f', 't', or 'w' |
| 1977 | ** for check-in, forum, ticket, or wiki. The remaining text is a |
| 1978 | ** integer that references the EVENT.OBJID value for the event. |
| 1979 | ** Run /timeline?showid to see these OBJID values. |
| 1980 | ** |
| 1981 | ** If the --backoffice option is included, then email_backoffice() is run |
| 1982 | ** after all alerts have been added. This will cause the alerts to |
| @@ -2008,11 +2008,35 @@ | |
| 2008 | #define SENDALERT_TRACE 0x0008 /* Trace operation for debugging */ |
| 2009 | |
| 2010 | #endif /* INTERFACE */ |
| 2011 | |
| 2012 | /* |
| 2013 | ** Send alert emails to subscribers. |
| 2014 | ** |
| 2015 | ** This procedure is run by either the backoffice, or in response to the |
| 2016 | ** "fossil alerts send" command. Details of operation are controlled by |
| 2017 | ** the flags parameter. |
| 2018 | ** |
| 2019 | ** Here is a summary of what happens: |
| 2020 | ** |
| 2021 | ** (1) Create a TEMP table wantalert(eventId,needMod) and fill it with |
| 2022 | ** all the events that we want to send alerts about. The needMod |
| 2023 | ** flags is set if and only if the event is still awaiting |
| 2024 | ** moderator approval. Events with the needMod flag are only |
| 2025 | ** shown to users that have moderator privileges. |
| 2026 | ** |
| 2027 | ** (2) Call email_compute_event_text() to compute a list of EmailEvent |
| 2028 | ** objects that describe all events about which we want to send |
| 2029 | ** alerts. |
| 2030 | ** |
| 2031 | ** (3) Loop over all subscribers. Compose and send one or more email |
| 2032 | ** messages to each subscriber that describe the events for |
| 2033 | ** which the subscriber has expressed interest and has |
| 2034 | ** appropriate privileges. |
| 2035 | ** |
| 2036 | ** (4) Update the pending_alerts table to indicate that alerts have been |
| 2037 | ** sent. |
| 2038 | */ |
| 2039 | void email_send_alerts(u32 flags){ |
| 2040 | EmailEvent *pEvents, *p; |
| 2041 | int nEvent = 0; |
| 2042 | Stmt q; |
| 2043 |
+2
-1
| --- src/webmail.c | ||
| +++ src/webmail.c | ||
| @@ -708,11 +708,11 @@ | ||
| 708 | 708 | @ <tr><td align="left"> |
| 709 | 709 | if( d==2 ){ |
| 710 | 710 | @ <input type="submit" name="read" value="Undelete"> |
| 711 | 711 | @ <input type="submit" name="purge" value="Delete Permanently"> |
| 712 | 712 | }else{ |
| 713 | - @ <input type="submit" name="trash", value="Delete"> | |
| 713 | + @ <input type="submit" name="trash" value="Delete"> | |
| 714 | 714 | if( d!=1 ){ |
| 715 | 715 | @ <input type="submit" name="unread" value="Mark as unread"> |
| 716 | 716 | } |
| 717 | 717 | @ <input type="submit" name="read" value="Mark as read"> |
| 718 | 718 | } |
| @@ -732,10 +732,11 @@ | ||
| 732 | 732 | while( db_step(&q)==SQLITE_ROW ){ |
| 733 | 733 | const char *zId = db_column_text(&q,0); |
| 734 | 734 | const char *zFrom = db_column_text(&q, 1); |
| 735 | 735 | const char *zDate = db_column_text(&q, 2); |
| 736 | 736 | const char *zSubject = db_column_text(&q, 4); |
| 737 | + if( zSubject==0 || zSubject[0]==0 ) zSubject = "(no subject)"; | |
| 737 | 738 | @ <tr> |
| 738 | 739 | @ <td><input type="checkbox" class="webmailckbox" name="e%s(zId)"></td> |
| 739 | 740 | @ <td>%h(zFrom)</td> |
| 740 | 741 | @ <td><a href="%s(url_render(&url,"id",zId,0,0))">%h(zSubject)</a> \ |
| 741 | 742 | @ %s(zDate)</td> |
| 742 | 743 |
| --- src/webmail.c | |
| +++ src/webmail.c | |
| @@ -708,11 +708,11 @@ | |
| 708 | @ <tr><td align="left"> |
| 709 | if( d==2 ){ |
| 710 | @ <input type="submit" name="read" value="Undelete"> |
| 711 | @ <input type="submit" name="purge" value="Delete Permanently"> |
| 712 | }else{ |
| 713 | @ <input type="submit" name="trash", value="Delete"> |
| 714 | if( d!=1 ){ |
| 715 | @ <input type="submit" name="unread" value="Mark as unread"> |
| 716 | } |
| 717 | @ <input type="submit" name="read" value="Mark as read"> |
| 718 | } |
| @@ -732,10 +732,11 @@ | |
| 732 | while( db_step(&q)==SQLITE_ROW ){ |
| 733 | const char *zId = db_column_text(&q,0); |
| 734 | const char *zFrom = db_column_text(&q, 1); |
| 735 | const char *zDate = db_column_text(&q, 2); |
| 736 | const char *zSubject = db_column_text(&q, 4); |
| 737 | @ <tr> |
| 738 | @ <td><input type="checkbox" class="webmailckbox" name="e%s(zId)"></td> |
| 739 | @ <td>%h(zFrom)</td> |
| 740 | @ <td><a href="%s(url_render(&url,"id",zId,0,0))">%h(zSubject)</a> \ |
| 741 | @ %s(zDate)</td> |
| 742 |
| --- src/webmail.c | |
| +++ src/webmail.c | |
| @@ -708,11 +708,11 @@ | |
| 708 | @ <tr><td align="left"> |
| 709 | if( d==2 ){ |
| 710 | @ <input type="submit" name="read" value="Undelete"> |
| 711 | @ <input type="submit" name="purge" value="Delete Permanently"> |
| 712 | }else{ |
| 713 | @ <input type="submit" name="trash" value="Delete"> |
| 714 | if( d!=1 ){ |
| 715 | @ <input type="submit" name="unread" value="Mark as unread"> |
| 716 | } |
| 717 | @ <input type="submit" name="read" value="Mark as read"> |
| 718 | } |
| @@ -732,10 +732,11 @@ | |
| 732 | while( db_step(&q)==SQLITE_ROW ){ |
| 733 | const char *zId = db_column_text(&q,0); |
| 734 | const char *zFrom = db_column_text(&q, 1); |
| 735 | const char *zDate = db_column_text(&q, 2); |
| 736 | const char *zSubject = db_column_text(&q, 4); |
| 737 | if( zSubject==0 || zSubject[0]==0 ) zSubject = "(no subject)"; |
| 738 | @ <tr> |
| 739 | @ <td><input type="checkbox" class="webmailckbox" name="e%s(zId)"></td> |
| 740 | @ <td>%h(zFrom)</td> |
| 741 | @ <td><a href="%s(url_render(&url,"id",zId,0,0))">%h(zSubject)</a> \ |
| 742 | @ %s(zDate)</td> |
| 743 |