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.
Commit
775e529b32022e378b4d0abd30f7fb49999af9fb1e041f79789ef2084dcbb316
Parent
84d0d853177588e…
1 file changed
+63
-4
+63
-4
| --- src/email.c | ||
| +++ src/email.c | ||
| @@ -178,10 +178,19 @@ | ||
| 178 | 178 | "eadmin", "", 0); |
| 179 | 179 | @ <p>This is the email for the human administrator for the system. |
| 180 | 180 | @ Abuse and trouble reports are send here. |
| 181 | 181 | @ (Property: "email-admin")</p> |
| 182 | 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> | |
| 183 | 192 | @ <p><input type="submit" name="submit" value="Apply Changes" /></p> |
| 184 | 193 | @ </div></form> |
| 185 | 194 | db_end_transaction(0); |
| 186 | 195 | style_footer(); |
| 187 | 196 | } |
| @@ -197,10 +206,23 @@ | ||
| 197 | 206 | k = translateBase64(blob_buffer(pMsg)+i, i+54<n ? 54 : n-i, zBuf); |
| 198 | 207 | blob_append(pOut, zBuf, k); |
| 199 | 208 | blob_append(pOut, "\r\n", 2); |
| 200 | 209 | } |
| 201 | 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 | +} | |
| 202 | 224 | |
| 203 | 225 | #if defined(_WIN32) || defined(WIN32) |
| 204 | 226 | # undef popen |
| 205 | 227 | # define popen _popen |
| 206 | 228 | # undef pclose |
| @@ -306,20 +328,32 @@ | ||
| 306 | 328 | fclose(out); |
| 307 | 329 | } |
| 308 | 330 | } |
| 309 | 331 | }else if( strcmp(zDest, "dir")==0 ){ |
| 310 | 332 | 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); | |
| 314 | 334 | blob_write_to_file(&all, zFile); |
| 315 | 335 | fossil_free(zFile); |
| 316 | 336 | }else if( strcmp(zDest, "stdout")==0 ){ |
| 317 | 337 | fossil_print("%s\n", blob_str(&all)); |
| 318 | 338 | } |
| 319 | 339 | blob_zero(&all); |
| 320 | 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 | +} | |
| 321 | 355 | |
| 322 | 356 | /* |
| 323 | 357 | ** SETTING: email-send-method width=5 default=off |
| 324 | 358 | ** Determine the method used to send email. Allowed values are |
| 325 | 359 | ** "off", "pipe", "dir", "db", and "stdout". The "off" value means |
| @@ -351,18 +385,28 @@ | ||
| 351 | 385 | /* |
| 352 | 386 | ** SETTING: email-self width=40 |
| 353 | 387 | ** This is the email address for the repository. Outbound emails add |
| 354 | 388 | ** this email address as the "From:" field. |
| 355 | 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 | +*/ | |
| 356 | 396 | |
| 357 | 397 | |
| 358 | 398 | /* |
| 359 | 399 | ** COMMAND: email |
| 360 | 400 | ** |
| 361 | 401 | ** Usage: %fossil email SUBCOMMAND ARGS... |
| 362 | 402 | ** |
| 363 | 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. | |
| 364 | 408 | ** |
| 365 | 409 | ** reset Hard reset of all email notification tables |
| 366 | 410 | ** in the repository. This erases all subscription |
| 367 | 411 | ** information. Use with extreme care. |
| 368 | 412 | ** |
| @@ -384,10 +428,25 @@ | ||
| 384 | 428 | int nCmd; |
| 385 | 429 | db_find_and_open_repository(0, 0); |
| 386 | 430 | email_schema(); |
| 387 | 431 | zCmd = g.argc>=3 ? g.argv[2] : "x"; |
| 388 | 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 | |
| 389 | 448 | if( strncmp(zCmd, "reset", nCmd)==0 ){ |
| 390 | 449 | Blob yn; |
| 391 | 450 | int c; |
| 392 | 451 | fossil_print( |
| 393 | 452 | "This will erase all content in the repository tables, thus\n" |
| @@ -466,11 +525,11 @@ | ||
| 466 | 525 | if( strncmp(pSetting->name,"email-",6)!=0 ) continue; |
| 467 | 526 | print_setting(pSetting); |
| 468 | 527 | } |
| 469 | 528 | } |
| 470 | 529 | else{ |
| 471 | - usage("reset|send|setting"); | |
| 530 | + usage("inbound|reset|send|setting"); | |
| 472 | 531 | } |
| 473 | 532 | } |
| 474 | 533 | |
| 475 | 534 | /* |
| 476 | 535 | ** Do error checking on a submitted subscription form. Return TRUE |
| 477 | 536 |
| --- 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 |