44
45
#define NTFY_MAILTO_MAX_RECIPIENTS 8
45
46
#define NTFY_MAILTO_MAX_HEADERS 16
46
47
#define NTFY_MAILTO_MAX_SUBJECT 256
49
50
* Mailto notification method
52
53
static bool ntfy_mailto_compile_check_uri
53
54
(const struct sieve_enotify_env *nenv, const char *uri, const char *uri_body);
54
55
static bool ntfy_mailto_compile_check_from
55
56
(const struct sieve_enotify_env *nenv, string_t *from);
57
58
static const char *ntfy_mailto_runtime_get_notify_capability
58
(const struct sieve_enotify_env *nenv, const char *uri, const char *uri_body,
59
(const struct sieve_enotify_env *nenv, const char *uri, const char *uri_body,
59
60
const char *capability);
60
61
static bool ntfy_mailto_runtime_check_uri
61
62
(const struct sieve_enotify_env *nenv, const char *uri, const char *uri_body);
62
63
static bool ntfy_mailto_runtime_check_operands
63
(const struct sieve_enotify_env *nenv, const char *uri,const char *uri_body,
64
string_t *message, string_t *from, pool_t context_pool,
64
(const struct sieve_enotify_env *nenv, const char *uri,const char *uri_body,
65
string_t *message, string_t *from, pool_t context_pool,
65
66
void **method_context);
67
68
static int ntfy_mailto_action_check_duplicates
68
(const struct sieve_enotify_env *nenv,
69
(const struct sieve_enotify_env *nenv,
69
70
const struct sieve_enotify_action *nact,
70
71
const struct sieve_enotify_action *nact_other);
72
73
static void ntfy_mailto_action_print
73
(const struct sieve_enotify_print_env *penv,
74
const struct sieve_enotify_action *nact);
74
(const struct sieve_enotify_print_env *penv,
75
const struct sieve_enotify_action *nact);
76
77
static bool ntfy_mailto_action_execute
77
(const struct sieve_enotify_exec_env *nenv,
78
(const struct sieve_enotify_exec_env *nenv,
78
79
const struct sieve_enotify_action *nact);
80
81
const struct sieve_enotify_method_def mailto_notify = {
83
84
ntfy_mailto_compile_check_uri,
85
86
ntfy_mailto_compile_check_from,
369
370
if ((*s & 0x80) != 0)
376
377
static bool ntfy_mailto_send
377
(const struct sieve_enotify_exec_env *nenv,
378
(const struct sieve_enotify_exec_env *nenv,
378
379
const struct sieve_enotify_action *nact, const char *recipient)
380
381
const struct sieve_message_data *msgdata = nenv->msgdata;
381
382
const struct sieve_script_env *senv = nenv->scriptenv;
382
struct ntfy_mailto_context *mtctx =
383
(struct ntfy_mailto_context *) nact->method_context;
384
const char *from = NULL, *from_smtp = NULL;
383
struct ntfy_mailto_context *mtctx =
384
(struct ntfy_mailto_context *) nact->method_context;
385
const char *from = NULL, *from_smtp = NULL;
385
386
const char *subject = mtctx->uri->subject;
386
387
const char *body = mtctx->uri->body;
387
388
string_t *to, *cc;
388
389
const struct uri_mailto_recipient *recipients;
390
const struct uri_mailto_header_field *headers;
389
391
void *smtp_handle;
390
unsigned int count, i;
392
struct ostream *output;
394
unsigned int count, i, hcount, h;
392
395
const char *outmsgid;
394
397
/* Get recipients */
395
398
recipients = array_get(&mtctx->uri->recipients, &count);
396
399
if ( count == 0 ) {
397
sieve_enotify_warning(nenv,
400
sieve_enotify_warning(nenv,
398
401
"notify mailto uri specifies no recipients; action has no effect");
402
405
/* Just to be sure */
403
406
if ( !sieve_smtp_available(senv) ) {
404
sieve_enotify_global_warning(nenv,
407
sieve_enotify_global_warning(nenv,
405
408
"notify mailto method has no means to send mail");
409
412
/* Determine message from address */
410
413
if ( nact->from == NULL ) {
411
414
from = t_strdup_printf("Postmaster <%s>", senv->postmaster_address);
467
msg = t_str_new(512);
468
outmsgid = sieve_message_get_new_id(nenv->svinst);
470
rfc2822_header_write(msg, "X-Sieve", SIEVE_IMPLEMENTATION);
471
rfc2822_header_write(msg, "Message-ID", outmsgid);
472
rfc2822_header_write(msg, "Date", message_date_create(ioloop_time));
473
rfc2822_header_utf8_printf(msg, "Subject", "%s", subject);
475
rfc2822_header_utf8_printf(msg, "From", "%s", from);
478
rfc2822_header_utf8_printf(msg, "To", "%s", str_c(to));
481
rfc2822_header_utf8_printf(msg, "Cc", "%s", str_c(cc));
483
rfc2822_header_printf(msg, "Auto-Submitted",
484
"auto-notified; owner-email=\"%s\"", recipient);
485
rfc2822_header_write(msg, "Precedence", "bulk");
488
switch ( nact->importance ) {
490
rfc2822_header_write(msg, "X-Priority", "1 (Highest)");
491
rfc2822_header_write(msg, "Importance", "High");
494
rfc2822_header_write(msg, "X-Priority", "5 (Lowest)");
495
rfc2822_header_write(msg, "Importance", "Low");
499
rfc2822_header_write(msg, "X-Priority", "3 (Normal)");
500
rfc2822_header_write(msg, "Importance", "Normal");
504
/* Add custom headers */
506
headers = array_get(&mtctx->uri->headers, &hcount);
507
for ( h = 0; h < hcount; h++ ) {
508
const char *name = rfc2822_header_field_name_sanitize(headers[h].name);
510
rfc2822_header_write(msg, name, headers[h].body);
513
/* Generate message body */
515
rfc2822_header_write(msg, "MIME-Version", "1.0");
516
if ( body != NULL ) {
517
if (_contains_8bit(body)) {
519
(msg, "Content-Type", "text/plain; charset=utf-8");
520
rfc2822_header_write(msg, "Content-Transfer-Encoding", "8bit");
523
(msg, "Content-Type", "text/plain; charset=us-ascii");
524
rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit");
526
str_printfa(msg, "\r\n%s\r\n", body);
530
(msg, "Content-Type", "text/plain; charset=US-ASCII");
531
rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit");
533
str_append(msg, "\r\nNotification of new message.\r\n");
464
536
/* Send message to all recipients */
465
537
for ( i = 0; i < count; i++ ) {
466
const struct uri_mailto_header_field *headers;
467
unsigned int h, hcount;
469
538
smtp_handle = sieve_smtp_open
470
(senv, recipients[i].normalized, from_smtp, &f);
471
outmsgid = sieve_message_get_new_id(nenv->svinst);
473
rfc2822_header_field_write(f, "X-Sieve", SIEVE_IMPLEMENTATION);
474
rfc2822_header_field_write(f, "Message-ID", outmsgid);
475
rfc2822_header_field_write(f, "Date", message_date_create(ioloop_time));
476
rfc2822_header_field_utf8_printf(f, "Subject", "%s", subject);
478
rfc2822_header_field_utf8_printf(f, "From", "%s", from);
481
rfc2822_header_field_utf8_printf(f, "To", "%s", str_c(to));
484
rfc2822_header_field_utf8_printf(f, "Cc", "%s", str_c(cc));
486
rfc2822_header_field_printf(f, "Auto-Submitted",
487
"auto-notified; owner-email=\"%s\"", recipient);
488
rfc2822_header_field_write(f, "Precedence", "bulk");
491
switch ( nact->importance ) {
493
rfc2822_header_field_write(f, "X-Priority", "1 (Highest)");
494
rfc2822_header_field_write(f, "Importance", "High");
497
rfc2822_header_field_write(f, "X-Priority", "5 (Lowest)");
498
rfc2822_header_field_write(f, "Importance", "Low");
502
rfc2822_header_field_write(f, "X-Priority", "3 (Normal)");
503
rfc2822_header_field_write(f, "Importance", "Normal");
507
/* Add custom headers */
509
headers = array_get(&mtctx->uri->headers, &hcount);
510
for ( h = 0; h < hcount; h++ ) {
511
const char *name = rfc2822_header_field_name_sanitize(headers[h].name);
513
rfc2822_header_field_write(f, name, headers[h].body);
516
/* Generate message body */
517
if ( body != NULL ) {
518
if (_contains_8bit(body)) {
519
rfc2822_header_field_write(f, "MIME-Version", "1.0");
520
rfc2822_header_field_write
521
(f, "Content-Type", "text/plain; charset=UTF-8");
522
rfc2822_header_field_write(f, "Content-Transfer-Encoding", "8bit");
526
fprintf(f, "%s\r\n", body);
530
fprintf(f, "Notification of new message.\r\n");
539
(senv, recipients[i].normalized, from_smtp, &output);
541
o_stream_send(output, str_data(msg), str_len(msg));
533
543
if ( sieve_smtp_close(senv, smtp_handle) ) {
534
sieve_enotify_global_info(nenv,
535
"sent mail notification to <%s>",
544
sieve_enotify_global_info(nenv,
545
"sent mail notification to <%s>",
536
546
str_sanitize(recipients[i].normalized, 80));
538
548
sieve_enotify_global_error(nenv,
539
549
"failed to send mail notification to <%s> "
540
"(refer to system log for more information)",
550
"(refer to system log for more information)",
541
551
str_sanitize(recipients[i].normalized, 80));