Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Attempt to provide improved error message outputs for failures while trying to send notification via relay to an MTA. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
e6c27d3dabf0c3631e09f8212002c7d0 |
| User & Date: | drh 2025-04-15 23:34:25.954 |
Context
|
2025-04-16
| ||
| 00:48 | Automatic retry on an SMTP relay failure. check-in: 2b96941c4c user: drh tags: trunk | |
|
2025-04-15
| ||
| 23:34 | Attempt to provide improved error message outputs for failures while trying to send notification via relay to an MTA. check-in: e6c27d3dab user: drh tags: trunk | |
| 15:56 | Two new settings "show-repolist-desc" and "show-repolist-lg" control whether or not the description and the login-group are shown on the repolist, respectively. These settings must be global to be effective. They default to "off". check-in: 1760fa2bf4 user: drh tags: trunk | |
Changes
Changes to src/alerts.c.
| ︙ | ︙ | |||
1031 1032 1033 1034 1035 1036 1037 1038 |
}else if( p->zDir ){
char *zFile = file_time_tempname(p->zDir, ".email");
blob_write_to_file(&all, zFile);
fossil_free(zFile);
}else if( p->pSmtp ){
char **azTo = 0;
int nTo = 0;
email_header_to(pHdr, &nTo, &azTo);
| > | | > > > > > > > | 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 |
}else if( p->zDir ){
char *zFile = file_time_tempname(p->zDir, ".email");
blob_write_to_file(&all, zFile);
fossil_free(zFile);
}else if( p->pSmtp ){
char **azTo = 0;
int nTo = 0;
SmtpSession *pSmtp = p->pSmtp;
email_header_to(pHdr, &nTo, &azTo);
if( nTo>0 && !pSmtp->bFatal ){
smtp_send_msg(pSmtp,p->zFrom,nTo,(const char**)azTo,blob_str(&all));
if( pSmtp->zErr && !pSmtp->bFatal ){
smtp_send_msg(pSmtp,p->zFrom,nTo,(const char**)azTo,blob_str(&all));
}
if( pSmtp->zErr ){
fossil_errorlog("SMTP: (%s) %s", pSmtp->bFatal ? "fatal" : "retry",
pSmtp->zErr);
}
email_header_to_free(nTo, azTo);
}
}else if( strcmp(p->zDest, "stdout")==0 ){
char **azTo = 0;
int nTo = 0;
int i;
email_header_to(pHdr, &nTo, &azTo);
|
| ︙ | ︙ |
Changes to src/printf.c.
| ︙ | ︙ | |||
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 |
void fossil_errorlog(const char *zFormat, ...){
struct tm *pNow;
time_t now;
FILE *out;
const char *z;
int i;
int bDetail = 0;
va_list ap;
static const char *const azEnv[] = { "HTTP_HOST", "HTTP_REFERER",
"HTTP_USER_AGENT",
"PATH_INFO", "QUERY_STRING", "REMOTE_ADDR", "REQUEST_METHOD",
"REQUEST_URI", "SCRIPT_NAME" };
if( g.zErrlog==0 ) return;
if( g.zErrlog[0]=='-' && g.zErrlog[1]==0 ){
| > | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 |
void fossil_errorlog(const char *zFormat, ...){
struct tm *pNow;
time_t now;
FILE *out;
const char *z;
int i;
int bDetail = 0;
int bBrief = 0;
va_list ap;
static const char *const azEnv[] = { "HTTP_HOST", "HTTP_REFERER",
"HTTP_USER_AGENT",
"PATH_INFO", "QUERY_STRING", "REMOTE_ADDR", "REQUEST_METHOD",
"REQUEST_URI", "SCRIPT_NAME" };
if( g.zErrlog==0 ) return;
if( g.zErrlog[0]=='-' && g.zErrlog[1]==0 ){
|
| ︙ | ︙ | |||
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 |
fprintf(out, "------------- %04d-%02d-%02d %02d:%02d:%02d UTC ------------\n",
pNow->tm_year+1900, pNow->tm_mon+1, pNow->tm_mday,
pNow->tm_hour, pNow->tm_min, pNow->tm_sec);
va_start(ap, zFormat);
if( zFormat[0]=='X' ){
bDetail = 1;
zFormat++;
}
vfprintf(out, zFormat, ap);
fprintf(out, " (pid %d)\n", (int)getpid());
va_end(ap);
if( g.zPhase!=0 ) fprintf(out, "while in %s\n", g.zPhase);
| > > > > | | 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 |
fprintf(out, "------------- %04d-%02d-%02d %02d:%02d:%02d UTC ------------\n",
pNow->tm_year+1900, pNow->tm_mon+1, pNow->tm_mday,
pNow->tm_hour, pNow->tm_min, pNow->tm_sec);
va_start(ap, zFormat);
if( zFormat[0]=='X' ){
bDetail = 1;
zFormat++;
}else if( strncmp(zFormat,"SMTP:",5)==0 ){
bBrief = 1;
}
vfprintf(out, zFormat, ap);
fprintf(out, " (pid %d)\n", (int)getpid());
va_end(ap);
if( g.zPhase!=0 ) fprintf(out, "while in %s\n", g.zPhase);
if( bBrief ){
/* Say nothing more */
}else if( bDetail ){
cgi_print_all(1,3,out);
}else{
for(i=0; i<count(azEnv); i++){
char *p;
if( (p = fossil_getenv(azEnv[i]))!=0 && p[0]!=0 ){
fprintf(out, "%s=%s\n", azEnv[i], p);
fossil_path_free(p);
|
| ︙ | ︙ |
Changes to src/smtp.c.
| ︙ | ︙ | |||
155 156 157 158 159 160 161 162 163 164 165 166 167 168 | const char *zFrom; /* Domain from which we are sending */ const char *zDest; /* Domain that will receive the email */ char *zHostname; /* Hostname of SMTP server for zDest */ u32 smtpFlags; /* Flags changing the operation */ FILE *logFile; /* Write session transcript to this log file */ Blob *pTranscript; /* Record session transcript here */ int atEof; /* True after connection closes */ char *zErr; /* Error message */ Blob inbuf; /* Input buffer */ }; /* Allowed values for SmtpSession.smtpFlags */ #define SMTP_TRACE_STDOUT 0x00001 /* Debugging info to console */ #define SMTP_TRACE_FILE 0x00002 /* Debugging info to logFile */ | > | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | const char *zFrom; /* Domain from which we are sending */ const char *zDest; /* Domain that will receive the email */ char *zHostname; /* Hostname of SMTP server for zDest */ u32 smtpFlags; /* Flags changing the operation */ FILE *logFile; /* Write session transcript to this log file */ Blob *pTranscript; /* Record session transcript here */ int atEof; /* True after connection closes */ int bFatal; /* Error is fatal. Do not retry */ char *zErr; /* Error message */ Blob inbuf; /* Input buffer */ }; /* Allowed values for SmtpSession.smtpFlags */ #define SMTP_TRACE_STDOUT 0x00001 /* Debugging info to console */ #define SMTP_TRACE_FILE 0x00002 /* Debugging info to logFile */ |
| ︙ | ︙ | |||
178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
void smtp_session_free(SmtpSession *pSession){
socket_close();
blob_reset(&pSession->inbuf);
fossil_free(pSession->zHostname);
fossil_free(pSession->zErr);
fossil_free(pSession);
}
/*
** Allocate a new SmtpSession object.
**
** Both zFrom and zDest must be specified. smtpFlags may not contain
** either SMTP_TRACE_FILE or SMTP_TRACE_BLOB as those settings must be
** added by a subsequent call to smtp_session_config().
| > > > > > > > > > > > > > > > > > > > > | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
void smtp_session_free(SmtpSession *pSession){
socket_close();
blob_reset(&pSession->inbuf);
fossil_free(pSession->zHostname);
fossil_free(pSession->zErr);
fossil_free(pSession);
}
/*
** Set an error message on the SmtpSession
*/
static void smtp_set_error(
SmtpSession *p, /* The SMTP context */
int bFatal, /* Fatal error. Reset and retry is pointless */
const char *zFormat, /* Error message. */
...
){
if( bFatal ) p->bFatal = 1;
if( p->zErr==0 ){
va_list ap;
va_start(ap, zFormat);
p->zErr = vmprintf(zFormat, ap);
va_end(ap);
}
socket_close();
p->atEof = 1;
}
/*
** Allocate a new SmtpSession object.
**
** Both zFrom and zDest must be specified. smtpFlags may not contain
** either SMTP_TRACE_FILE or SMTP_TRACE_BLOB as those settings must be
** added by a subsequent call to smtp_session_config().
|
| ︙ | ︙ | |||
220 221 222 223 224 225 226 |
p->zHostname[i] = 0;
url.port = atoi(&p->zHostname[i+1]);
}
}else{
p->zHostname = smtp_mx_host(zDest);
}
if( p->zHostname==0 ){
| < | < | < | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
p->zHostname[i] = 0;
url.port = atoi(&p->zHostname[i+1]);
}
}else{
p->zHostname = smtp_mx_host(zDest);
}
if( p->zHostname==0 ){
smtp_set_error(p, 1, "cannot locate SMTP server for \"%s\"", zDest);
return p;
}
url.name = p->zHostname;
socket_global_init();
if( socket_open(&url) ){
smtp_set_error(p, 1, "can't open socket: %z", socket_errmsg());
}
return p;
}
/*
** Configure debugging options on SmtpSession. Add all bits in
** smtpFlags to the settings. The following bits can be added:
|
| ︙ | ︙ | |||
318 319 320 321 322 323 324 |
z[n] = 0;
if( n>0 && z[n-1]=='\n' ) break;
if( got==1000 ) continue;
}
nDelay++;
if( nDelay>100 ){
blob_init(in, 0, 0);
| | < < | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
z[n] = 0;
if( n>0 && z[n-1]=='\n' ) break;
if( got==1000 ) continue;
}
nDelay++;
if( nDelay>100 ){
blob_init(in, 0, 0);
smtp_set_error(p, 1, "client times out waiting on server response");
return;
}else{
sqlite3_sleep(100);
}
}while( n<1 || z[n-1]!='\n' );
blob_truncate(&p->inbuf, n);
blob_line(&p->inbuf, in);
|
| ︙ | ︙ | |||
401 402 403 404 405 406 407 |
** Return 0 on success and non-zero for a failure.
*/
int smtp_client_startup(SmtpSession *p){
Blob in = BLOB_INITIALIZER;
int iCode = 0;
int bMore = 0;
char *zArg = 0;
| | > > > > | 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 |
** Return 0 on success and non-zero for a failure.
*/
int smtp_client_startup(SmtpSession *p){
Blob in = BLOB_INITIALIZER;
int iCode = 0;
int bMore = 0;
char *zArg = 0;
if( p==0 || p->bFatal ) return 1;
fossil_free(p->zErr);
p->zErr = 0;
do{
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
}while( bMore );
if( iCode!=220 ){
smtp_set_error(p, 1, "server opens conversation with: %b", &in);
smtp_client_quit(p);
return 1;
}
smtp_send_line(p, "EHLO %s\r\n", p->zFrom);
do{
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
}while( bMore );
if( iCode!=250 ){
smtp_set_error(p, 1, "server responds to EHLO with: %b", &in);
smtp_client_quit(p);
return 1;
}
return 0;
}
/*
|
| ︙ | ︙ | |||
548 549 550 551 552 553 554 555 556 557 558 |
){
int i;
int iCode = 0;
int bMore = 0;
char *zArg = 0;
Blob in;
blob_init(&in, 0, 0);
smtp_send_line(p, "MAIL FROM:<%s>\r\n", zFrom);
do{
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
}while( bMore );
| > > > > | > > > | > > > | > > > | > > > | 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 |
){
int i;
int iCode = 0;
int bMore = 0;
char *zArg = 0;
Blob in;
blob_init(&in, 0, 0);
if( p->atEof && !p->bFatal ){
smtp_client_startup(p);
if( p->atEof ) return 1;
}
smtp_send_line(p, "MAIL FROM:<%s>\r\n", zFrom);
do{
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
}while( bMore );
if( iCode!=250 ){
smtp_set_error(p, 0, "server replies to MAIL FROM with: %b", &in);
return 1;
}
for(i=0; i<nTo; i++){
smtp_send_line(p, "RCPT TO:<%s>\r\n", azTo[i]);
do{
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
}while( bMore );
if( iCode!=250 ){
smtp_set_error(p, 0, "server replies to RCPT TO with: %b", &in);
return 1;
}
}
smtp_send_line(p, "DATA\r\n");
do{
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
}while( bMore );
if( iCode!=354 ){
smtp_set_error(p, 0, "server replies to DATA with: %b", &in);
return 1;
}
smtp_send_email_body(zMsg, socket_send, 0);
if( p->smtpFlags & SMTP_TRACE_STDOUT ){
fossil_print("C: # message content\nC: .\n");
}
if( p->smtpFlags & SMTP_TRACE_FILE ){
fprintf(p->logFile, "C: # message content\nC: .\n");
}
if( p->smtpFlags & SMTP_TRACE_BLOB ){
blob_appendf(p->pTranscript, "C: # message content\nC: .\n");
}
do{
smtp_get_reply_from_server(p, &in, &iCode, &bMore, &zArg);
}while( bMore );
if( iCode!=250 ){
smtp_set_error(p, 0, "server replies to end-of-DATA with: %b", &in);
return 1;
}
return 0;
}
/*
** The input is a base email address of the form "local@domain".
** Return a pointer to just the "domain" part, or 0 if the string
** contains no "@".
|
| ︙ | ︙ | |||
644 645 646 647 648 649 650 |
}
p = smtp_session_new(zFromDomain, zToDomain, smtpFlags, smtpPort);
if( p->zErr ){
fossil_fatal("%s", p->zErr);
}
fossil_print("Connection to \"%s\"\n", p->zHostname);
smtp_client_startup(p);
| > | > | 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 |
}
p = smtp_session_new(zFromDomain, zToDomain, smtpFlags, smtpPort);
if( p->zErr ){
fossil_fatal("%s", p->zErr);
}
fossil_print("Connection to \"%s\"\n", p->zHostname);
smtp_client_startup(p);
if( !p->atEof ){
smtp_send_msg(p, zFrom, nTo, azTo, blob_str(&body));
}
smtp_client_quit(p);
if( p->zErr ){
fossil_fatal("ERROR: %s\n", p->zErr);
}
smtp_session_free(p);
blob_reset(&body);
}
|