Fossil SCM

Add the "fossil email inbound" command, though it currently does not analyze the inbound emails - it just stores the emails in a directory for later human viewing.

drh 2018-06-21 23:01 UTC email-alerts
Commit 775e529b32022e378b4d0abd30f7fb49999af9fb1e041f79789ef2084dcbb316
1 file changed +63 -4
+63 -4
--- src/email.c
+++ src/email.c
@@ -178,10 +178,19 @@
178178
"eadmin", "", 0);
179179
@ <p>This is the email for the human administrator for the system.
180180
@ Abuse and trouble reports are send here.
181181
@ (Property: "email-admin")</p>
182182
@ <hr>
183
+
184
+ entry_attribute("Inbound email directory", 40, "email-receive-dir",
185
+ "erdir", "", 0);
186
+ @ <p>Inbound emails can be stored in a directory for analysis as
187
+ @ a debugging aid. Put the name of that directory in this entry box.
188
+ @ Disable saving of inbound email by making this an empty string.
189
+ @ Abuse and trouble reports are send here.
190
+ @ (Property: "email-receive-dir")</p>
191
+ @ <hr>
183192
@ <p><input type="submit" name="submit" value="Apply Changes" /></p>
184193
@ </div></form>
185194
db_end_transaction(0);
186195
style_footer();
187196
}
@@ -197,10 +206,23 @@
197206
k = translateBase64(blob_buffer(pMsg)+i, i+54<n ? 54 : n-i, zBuf);
198207
blob_append(pOut, zBuf, k);
199208
blob_append(pOut, "\r\n", 2);
200209
}
201210
}
211
+
212
+/*
213
+** Come up with a unique filename in the zDir directory.
214
+**
215
+** Space to hold the filename is obtained from mprintf() and must
216
+** be freed using fossil_free() by the caller.
217
+*/
218
+static char *emailTempFilename(const char *zDir){
219
+ char *zFile = db_text(0,
220
+ "SELECT %Q||strftime('/%%Y%%m%%d%%H%%M%%S-','now')||hex(randomblob(8))",
221
+ zDir);
222
+ return zFile;
223
+}
202224
203225
#if defined(_WIN32) || defined(WIN32)
204226
# undef popen
205227
# define popen _popen
206228
# undef pclose
@@ -306,20 +328,32 @@
306328
fclose(out);
307329
}
308330
}
309331
}else if( strcmp(zDest, "dir")==0 ){
310332
const char *zDir = db_get("email-send-dir","./");
311
- char *zFile = db_text(0,
312
- "SELECT %Q||strftime('/%%Y%%m%%d%%H%%M%%S','now')||hex(randomblob(8))",
313
- zDir);
333
+ char *zFile = emailTempFilename(zDir);
314334
blob_write_to_file(&all, zFile);
315335
fossil_free(zFile);
316336
}else if( strcmp(zDest, "stdout")==0 ){
317337
fossil_print("%s\n", blob_str(&all));
318338
}
319339
blob_zero(&all);
320340
}
341
+
342
+/*
343
+** Analyze and act on a received email.
344
+**
345
+** This routine takes ownership of the Blob parameter and is responsible
346
+** for freeing that blob when it is done with it.
347
+**
348
+** This routine acts on all email messages received from the
349
+** "fossil email inbound" command.
350
+*/
351
+void email_receive(Blob *pMsg){
352
+ /* To Do: Look for bounce messages and possibly disable subscriptions */
353
+ blob_zero(pMsg);
354
+}
321355
322356
/*
323357
** SETTING: email-send-method width=5 default=off
324358
** Determine the method used to send email. Allowed values are
325359
** "off", "pipe", "dir", "db", and "stdout". The "off" value means
@@ -351,18 +385,28 @@
351385
/*
352386
** SETTING: email-self width=40
353387
** This is the email address for the repository. Outbound emails add
354388
** this email address as the "From:" field.
355389
*/
390
+/*
391
+** SETTING: email-receive-dir width=40
392
+** Inbound email messages are saved as separate files in this directory,
393
+** for debugging analysis. Disable saving of inbound emails omitting
394
+** this setting, or making it an empty string.
395
+*/
356396
357397
358398
/*
359399
** COMMAND: email
360400
**
361401
** Usage: %fossil email SUBCOMMAND ARGS...
362402
**
363403
** Subcommands:
404
+**
405
+** inbound [FILE] Receive an inbound email message. This message
406
+** is analyzed to see if it is a bounce, and if
407
+** necessary, subscribers may be disabled.
364408
**
365409
** reset Hard reset of all email notification tables
366410
** in the repository. This erases all subscription
367411
** information. Use with extreme care.
368412
**
@@ -384,10 +428,25 @@
384428
int nCmd;
385429
db_find_and_open_repository(0, 0);
386430
email_schema();
387431
zCmd = g.argc>=3 ? g.argv[2] : "x";
388432
nCmd = (int)strlen(zCmd);
433
+ if( strncmp(zCmd, "inbound", nCmd)==0 ){
434
+ Blob email;
435
+ const char *zInboundDir = db_get("email-receive-dir","");
436
+ verify_all_options();
437
+ if( g.argc!=3 && g.argc!=4 ){
438
+ usage("inbound [FILE]");
439
+ }
440
+ blob_read_from_file(&email, g.argc==3 ? "-" : g.argv[3], ExtFILE);
441
+ if( zInboundDir[0] ){
442
+ char *zFN = emailTempFilename(zInboundDir);
443
+ blob_write_to_file(&email, zFN);
444
+ fossil_free(zFN);
445
+ }
446
+ email_receive(&email);
447
+ }else
389448
if( strncmp(zCmd, "reset", nCmd)==0 ){
390449
Blob yn;
391450
int c;
392451
fossil_print(
393452
"This will erase all content in the repository tables, thus\n"
@@ -466,11 +525,11 @@
466525
if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
467526
print_setting(pSetting);
468527
}
469528
}
470529
else{
471
- usage("reset|send|setting");
530
+ usage("inbound|reset|send|setting");
472531
}
473532
}
474533
475534
/*
476535
** Do error checking on a submitted subscription form. Return TRUE
477536
--- src/email.c
+++ src/email.c
@@ -178,10 +178,19 @@
178 "eadmin", "", 0);
179 @ <p>This is the email for the human administrator for the system.
180 @ Abuse and trouble reports are send here.
181 @ (Property: "email-admin")</p>
182 @ <hr>
 
 
 
 
 
 
 
 
 
183 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
184 @ </div></form>
185 db_end_transaction(0);
186 style_footer();
187 }
@@ -197,10 +206,23 @@
197 k = translateBase64(blob_buffer(pMsg)+i, i+54<n ? 54 : n-i, zBuf);
198 blob_append(pOut, zBuf, k);
199 blob_append(pOut, "\r\n", 2);
200 }
201 }
 
 
 
 
 
 
 
 
 
 
 
 
 
202
203 #if defined(_WIN32) || defined(WIN32)
204 # undef popen
205 # define popen _popen
206 # undef pclose
@@ -306,20 +328,32 @@
306 fclose(out);
307 }
308 }
309 }else if( strcmp(zDest, "dir")==0 ){
310 const char *zDir = db_get("email-send-dir","./");
311 char *zFile = db_text(0,
312 "SELECT %Q||strftime('/%%Y%%m%%d%%H%%M%%S','now')||hex(randomblob(8))",
313 zDir);
314 blob_write_to_file(&all, zFile);
315 fossil_free(zFile);
316 }else if( strcmp(zDest, "stdout")==0 ){
317 fossil_print("%s\n", blob_str(&all));
318 }
319 blob_zero(&all);
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 /*
323 ** SETTING: email-send-method width=5 default=off
324 ** Determine the method used to send email. Allowed values are
325 ** "off", "pipe", "dir", "db", and "stdout". The "off" value means
@@ -351,18 +385,28 @@
351 /*
352 ** SETTING: email-self width=40
353 ** This is the email address for the repository. Outbound emails add
354 ** this email address as the "From:" field.
355 */
 
 
 
 
 
 
356
357
358 /*
359 ** COMMAND: email
360 **
361 ** Usage: %fossil email SUBCOMMAND ARGS...
362 **
363 ** Subcommands:
 
 
 
 
364 **
365 ** reset Hard reset of all email notification tables
366 ** in the repository. This erases all subscription
367 ** information. Use with extreme care.
368 **
@@ -384,10 +428,25 @@
384 int nCmd;
385 db_find_and_open_repository(0, 0);
386 email_schema();
387 zCmd = g.argc>=3 ? g.argv[2] : "x";
388 nCmd = (int)strlen(zCmd);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389 if( strncmp(zCmd, "reset", nCmd)==0 ){
390 Blob yn;
391 int c;
392 fossil_print(
393 "This will erase all content in the repository tables, thus\n"
@@ -466,11 +525,11 @@
466 if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
467 print_setting(pSetting);
468 }
469 }
470 else{
471 usage("reset|send|setting");
472 }
473 }
474
475 /*
476 ** Do error checking on a submitted subscription form. Return TRUE
477
--- src/email.c
+++ src/email.c
@@ -178,10 +178,19 @@
178 "eadmin", "", 0);
179 @ <p>This is the email for the human administrator for the system.
180 @ Abuse and trouble reports are send here.
181 @ (Property: "email-admin")</p>
182 @ <hr>
183
184 entry_attribute("Inbound email directory", 40, "email-receive-dir",
185 "erdir", "", 0);
186 @ <p>Inbound emails can be stored in a directory for analysis as
187 @ a debugging aid. Put the name of that directory in this entry box.
188 @ Disable saving of inbound email by making this an empty string.
189 @ Abuse and trouble reports are send here.
190 @ (Property: "email-receive-dir")</p>
191 @ <hr>
192 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
193 @ </div></form>
194 db_end_transaction(0);
195 style_footer();
196 }
@@ -197,10 +206,23 @@
206 k = translateBase64(blob_buffer(pMsg)+i, i+54<n ? 54 : n-i, zBuf);
207 blob_append(pOut, zBuf, k);
208 blob_append(pOut, "\r\n", 2);
209 }
210 }
211
212 /*
213 ** Come up with a unique filename in the zDir directory.
214 **
215 ** Space to hold the filename is obtained from mprintf() and must
216 ** be freed using fossil_free() by the caller.
217 */
218 static char *emailTempFilename(const char *zDir){
219 char *zFile = db_text(0,
220 "SELECT %Q||strftime('/%%Y%%m%%d%%H%%M%%S-','now')||hex(randomblob(8))",
221 zDir);
222 return zFile;
223 }
224
225 #if defined(_WIN32) || defined(WIN32)
226 # undef popen
227 # define popen _popen
228 # undef pclose
@@ -306,20 +328,32 @@
328 fclose(out);
329 }
330 }
331 }else if( strcmp(zDest, "dir")==0 ){
332 const char *zDir = db_get("email-send-dir","./");
333 char *zFile = emailTempFilename(zDir);
 
 
334 blob_write_to_file(&all, zFile);
335 fossil_free(zFile);
336 }else if( strcmp(zDest, "stdout")==0 ){
337 fossil_print("%s\n", blob_str(&all));
338 }
339 blob_zero(&all);
340 }
341
342 /*
343 ** Analyze and act on a received email.
344 **
345 ** This routine takes ownership of the Blob parameter and is responsible
346 ** for freeing that blob when it is done with it.
347 **
348 ** This routine acts on all email messages received from the
349 ** "fossil email inbound" command.
350 */
351 void email_receive(Blob *pMsg){
352 /* To Do: Look for bounce messages and possibly disable subscriptions */
353 blob_zero(pMsg);
354 }
355
356 /*
357 ** SETTING: email-send-method width=5 default=off
358 ** Determine the method used to send email. Allowed values are
359 ** "off", "pipe", "dir", "db", and "stdout". The "off" value means
@@ -351,18 +385,28 @@
385 /*
386 ** SETTING: email-self width=40
387 ** This is the email address for the repository. Outbound emails add
388 ** this email address as the "From:" field.
389 */
390 /*
391 ** SETTING: email-receive-dir width=40
392 ** Inbound email messages are saved as separate files in this directory,
393 ** for debugging analysis. Disable saving of inbound emails omitting
394 ** this setting, or making it an empty string.
395 */
396
397
398 /*
399 ** COMMAND: email
400 **
401 ** Usage: %fossil email SUBCOMMAND ARGS...
402 **
403 ** Subcommands:
404 **
405 ** inbound [FILE] Receive an inbound email message. This message
406 ** is analyzed to see if it is a bounce, and if
407 ** necessary, subscribers may be disabled.
408 **
409 ** reset Hard reset of all email notification tables
410 ** in the repository. This erases all subscription
411 ** information. Use with extreme care.
412 **
@@ -384,10 +428,25 @@
428 int nCmd;
429 db_find_and_open_repository(0, 0);
430 email_schema();
431 zCmd = g.argc>=3 ? g.argv[2] : "x";
432 nCmd = (int)strlen(zCmd);
433 if( strncmp(zCmd, "inbound", nCmd)==0 ){
434 Blob email;
435 const char *zInboundDir = db_get("email-receive-dir","");
436 verify_all_options();
437 if( g.argc!=3 && g.argc!=4 ){
438 usage("inbound [FILE]");
439 }
440 blob_read_from_file(&email, g.argc==3 ? "-" : g.argv[3], ExtFILE);
441 if( zInboundDir[0] ){
442 char *zFN = emailTempFilename(zInboundDir);
443 blob_write_to_file(&email, zFN);
444 fossil_free(zFN);
445 }
446 email_receive(&email);
447 }else
448 if( strncmp(zCmd, "reset", nCmd)==0 ){
449 Blob yn;
450 int c;
451 fossil_print(
452 "This will erase all content in the repository tables, thus\n"
@@ -466,11 +525,11 @@
525 if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
526 print_setting(pSetting);
527 }
528 }
529 else{
530 usage("inbound|reset|send|setting");
531 }
532 }
533
534 /*
535 ** Do error checking on a submitted subscription form. Return TRUE
536

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button