Diff
Not logged in

Differences From Artifact [c704f92554]:

To Artifact [b6d4f9ef2d]:


401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
416
417
  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 EmailSender flags */

#define EMAIL_IMMEDIATE_FAIL   0x0001   /* Call fossil_fatal() on any error */
#define EMAIL_SMTP_TRACE       0x0002   /* Write SMTP transcript to console */

#endif /* INTERFACE */

/*
** Shutdown an emailer.  Clear all information other than the error message.
*/
static void emailerShutdown(EmailSender *p){







|
>

|







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
541
542
543
544
545
546
547
548
  }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_SMTP_TRACE ) smtpFlags |= SMTP_TRACE_STDOUT;
      p->pSmtp = smtp_session_new(p->zFrom, zRelay, smtpFlags);
      smtp_client_startup(p->pSmtp);
    }
  }
  return p;
}








|







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
948
949
950
951
952
953
954
955
    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_SMTP_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);







|







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
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
  blob_reset(&out);
  db_end_transaction(0);
}

/*
** COMMAND:  test-add-alerts
**
** Usage: %fossil test-add-alerts 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.




*/
void test_add_alert_cmd(void){
  int i;

  db_find_and_open_repository(0, 0);
  verify_all_options();
  db_begin_transaction();
  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 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 */


#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;


  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;



  pSender = email_sender_new(zDest, 0);
  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"







|









>
>
>
>



>


|





>
>
>









>

















>










>
>
>
|







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
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124

/*
** 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.




*/
void email_auto_exec(void){
  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(0);
  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);
    }
  }
  db_commit_transaction();
}

/*
** WEBPAGE: contact_admin







>
>
>
>

|










|






|







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