supporting CC BCC when mailing.
Showing
8 changed files
with
202 additions
and
204 deletions
... | @@ -47,8 +47,7 @@ extern void mailer_destroy __P ((mailer_t *)); | ... | @@ -47,8 +47,7 @@ extern void mailer_destroy __P ((mailer_t *)); |
47 | extern int mailer_open __P ((mailer_t, int flags)); | 47 | extern int mailer_open __P ((mailer_t, int flags)); |
48 | extern int mailer_close __P ((mailer_t)); | 48 | extern int mailer_close __P ((mailer_t)); |
49 | 49 | ||
50 | extern int mailer_send_message __P ((mailer_t, const char *from, | 50 | extern int mailer_send_message __P ((mailer_t, message_t)); |
51 | const char *rcpt, int dsn, message_t)); | ||
52 | /* stream settings */ | 51 | /* stream settings */ |
53 | extern int mailer_get_stream __P ((mailer_t, stream_t *)); | 52 | extern int mailer_get_stream __P ((mailer_t, stream_t *)); |
54 | extern int mailer_set_stream __P ((mailer_t, stream_t)); | 53 | extern int mailer_set_stream __P ((mailer_t, stream_t)); | ... | ... |
... | @@ -50,6 +50,9 @@ extern int message_create __P ((message_t *, void *owner)); | ... | @@ -50,6 +50,9 @@ extern int message_create __P ((message_t *, void *owner)); |
50 | extern void message_destroy __P ((message_t *, void *owner)); | 50 | extern void message_destroy __P ((message_t *, void *owner)); |
51 | extern void * message_get_owner __P ((message_t)); | 51 | extern void * message_get_owner __P ((message_t)); |
52 | 52 | ||
53 | extern int message_ref __P ((message_t)); | ||
54 | #define message_unref(msg) message_destroy (&msg) | ||
55 | |||
53 | extern int message_get_header __P ((message_t, header_t *)); | 56 | extern int message_get_header __P ((message_t, header_t *)); |
54 | extern int message_set_header __P ((message_t, header_t, void *owner)); | 57 | extern int message_set_header __P ((message_t, header_t, void *owner)); |
55 | 58 | ... | ... |
... | @@ -74,8 +74,7 @@ struct _mailer | ... | @@ -74,8 +74,7 @@ struct _mailer |
74 | void (*_destroy) __P ((mailer_t)); | 74 | void (*_destroy) __P ((mailer_t)); |
75 | int (*_open) __P ((mailer_t, int flags)); | 75 | int (*_open) __P ((mailer_t, int flags)); |
76 | int (*_close) __P ((mailer_t)); | 76 | int (*_close) __P ((mailer_t)); |
77 | int (*_send_message) __P ((mailer_t, const char *from, const char *rcpt, | 77 | int (*_send_message) __P ((mailer_t, message_t)); |
78 | int dsn, message_t)); | ||
79 | }; | 78 | }; |
80 | 79 | ||
81 | /* Mail locks. */ | 80 | /* Mail locks. */ | ... | ... |
... | @@ -52,6 +52,9 @@ struct _message | ... | @@ -52,6 +52,9 @@ struct _message |
52 | mime_t mime; | 52 | mime_t mime; |
53 | observable_t observable; | 53 | observable_t observable; |
54 | 54 | ||
55 | /* Reference count. */ | ||
56 | int ref; | ||
57 | |||
55 | /* Holder for message_write. */ | 58 | /* Holder for message_write. */ |
56 | char *hdr_buf; | 59 | char *hdr_buf; |
57 | size_t hdr_buflen; | 60 | size_t hdr_buflen; | ... | ... |
... | @@ -156,12 +156,11 @@ mailer_close (mailer_t mailer) | ... | @@ -156,12 +156,11 @@ mailer_close (mailer_t mailer) |
156 | 156 | ||
157 | /* messages */ | 157 | /* messages */ |
158 | int | 158 | int |
159 | mailer_send_message (mailer_t mailer, const char *from, const char *rcpt, | 159 | mailer_send_message (mailer_t mailer, message_t msg) |
160 | int dsn, message_t msg) | ||
161 | { | 160 | { |
162 | if (mailer == NULL || mailer->_send_message == NULL) | 161 | if (mailer == NULL || mailer->_send_message == NULL) |
163 | return ENOSYS; | 162 | return ENOSYS; |
164 | return mailer->_send_message (mailer, from, rcpt, dsn, msg); | 163 | return mailer->_send_message (mailer, msg); |
165 | } | 164 | } |
166 | 165 | ||
167 | int | 166 | int | ... | ... |
... | @@ -50,6 +50,7 @@ message_create (message_t *pmsg, void *owner) | ... | @@ -50,6 +50,7 @@ message_create (message_t *pmsg, void *owner) |
50 | if (msg == NULL) | 50 | if (msg == NULL) |
51 | return ENOMEM; | 51 | return ENOMEM; |
52 | msg->owner = owner; | 52 | msg->owner = owner; |
53 | msg->ref = 1; | ||
53 | *pmsg = msg; | 54 | *pmsg = msg; |
54 | return 0; | 55 | return 0; |
55 | } | 56 | } |
... | @@ -61,6 +62,7 @@ message_destroy (message_t *pmsg, void *owner) | ... | @@ -61,6 +62,7 @@ message_destroy (message_t *pmsg, void *owner) |
61 | { | 62 | { |
62 | message_t msg = *pmsg; | 63 | message_t msg = *pmsg; |
63 | 64 | ||
65 | msg->ref--; | ||
64 | if (msg->owner == owner) | 66 | if (msg->owner == owner) |
65 | { | 67 | { |
66 | /* Notify the listeners. */ | 68 | /* Notify the listeners. */ |
... | @@ -91,6 +93,7 @@ message_destroy (message_t *pmsg, void *owner) | ... | @@ -91,6 +93,7 @@ message_destroy (message_t *pmsg, void *owner) |
91 | if (msg->mime) | 93 | if (msg->mime) |
92 | mime_destroy (&(msg->mime)); | 94 | mime_destroy (&(msg->mime)); |
93 | 95 | ||
96 | if (msg->ref <= 0) | ||
94 | free (msg); | 97 | free (msg); |
95 | } | 98 | } |
96 | /* Loose the link */ | 99 | /* Loose the link */ |
... | @@ -98,6 +101,14 @@ message_destroy (message_t *pmsg, void *owner) | ... | @@ -98,6 +101,14 @@ message_destroy (message_t *pmsg, void *owner) |
98 | } | 101 | } |
99 | } | 102 | } |
100 | 103 | ||
104 | int | ||
105 | message_ref (message_t msg) | ||
106 | { | ||
107 | if (msg) | ||
108 | msg->ref++; | ||
109 | return 0; | ||
110 | } | ||
111 | |||
101 | void * | 112 | void * |
102 | message_get_owner (message_t msg) | 113 | message_get_owner (message_t msg) |
103 | { | 114 | { |
... | @@ -132,7 +143,7 @@ message_set_header (message_t msg, header_t hdr, void *owner) | ... | @@ -132,7 +143,7 @@ message_set_header (message_t msg, header_t hdr, void *owner) |
132 | return EACCES; | 143 | return EACCES; |
133 | /* Make sure we destoy the old if it was own by the mesg */ | 144 | /* Make sure we destoy the old if it was own by the mesg */ |
134 | /* FIXME: I do not know if somebody has already a ref on this ? */ | 145 | /* FIXME: I do not know if somebody has already a ref on this ? */ |
135 | /* header_destroy (&(msg->header), msg); */ | 146 | header_destroy (&(msg->header), msg); |
136 | msg->header = hdr; | 147 | msg->header = hdr; |
137 | return 0; | 148 | return 0; |
138 | } | 149 | } |
... | @@ -165,7 +176,7 @@ message_set_body (message_t msg, body_t body, void *owner) | ... | @@ -165,7 +176,7 @@ message_set_body (message_t msg, body_t body, void *owner) |
165 | return EACCES; | 176 | return EACCES; |
166 | /* Make sure we destoy the old if it was own by the mesg. */ | 177 | /* Make sure we destoy the old if it was own by the mesg. */ |
167 | /* FIXME: I do not know if somebody has already a ref on this ? */ | 178 | /* FIXME: I do not know if somebody has already a ref on this ? */ |
168 | /* body_destroy (&(msg->body), msg); */ | 179 | body_destroy (&(msg->body), msg); |
169 | msg->body = body; | 180 | msg->body = body; |
170 | return 0; | 181 | return 0; |
171 | } | 182 | } |
... | @@ -177,6 +188,9 @@ message_set_stream (message_t msg, stream_t stream, void *owner) | ... | @@ -177,6 +188,9 @@ message_set_stream (message_t msg, stream_t stream, void *owner) |
177 | return EINVAL; | 188 | return EINVAL; |
178 | if (msg->owner != owner) | 189 | if (msg->owner != owner) |
179 | return EACCES; | 190 | return EACCES; |
191 | /* Make sure we destoy the old if it was own by the mesg. */ | ||
192 | /* FIXME: I do not know if somebody has already a ref on this ? */ | ||
193 | stream_destroy (&(msg->stream), msg); | ||
180 | msg->stream = stream; | 194 | msg->stream = stream; |
181 | return 0; | 195 | return 0; |
182 | } | 196 | } | ... | ... |
... | @@ -72,8 +72,7 @@ typedef struct _sendmail * sendmail_t; | ... | @@ -72,8 +72,7 @@ typedef struct _sendmail * sendmail_t; |
72 | static void sendmail_destroy (mailer_t); | 72 | static void sendmail_destroy (mailer_t); |
73 | static int sendmail_open (mailer_t, int); | 73 | static int sendmail_open (mailer_t, int); |
74 | static int sendmail_close (mailer_t); | 74 | static int sendmail_close (mailer_t); |
75 | static int sendmail_send_message (mailer_t, const char *from, const char *rcpt, | 75 | static int sendmail_send_message (mailer_t, message_t); |
76 | int dsn, message_t); | ||
77 | 76 | ||
78 | int | 77 | int |
79 | sendmail_init (mailer_t mailer) | 78 | sendmail_init (mailer_t mailer) |
... | @@ -148,8 +147,7 @@ sendmail_close (mailer_t mailer) | ... | @@ -148,8 +147,7 @@ sendmail_close (mailer_t mailer) |
148 | } | 147 | } |
149 | 148 | ||
150 | static int | 149 | static int |
151 | sendmail_send_message (mailer_t mailer, const char *from, const char *rcpt, | 150 | sendmail_send_message (mailer_t mailer, message_t msg) |
152 | int dsn, message_t msg) | ||
153 | { | 151 | { |
154 | sendmail_t sendmail = mailer->data; | 152 | sendmail_t sendmail = mailer->data; |
155 | int status = 0; | 153 | int status = 0; |
... | @@ -157,8 +155,6 @@ sendmail_send_message (mailer_t mailer, const char *from, const char *rcpt, | ... | @@ -157,8 +155,6 @@ sendmail_send_message (mailer_t mailer, const char *from, const char *rcpt, |
157 | if (sendmail == NULL || msg == NULL) | 155 | if (sendmail == NULL || msg == NULL) |
158 | return EINVAL; | 156 | return EINVAL; |
159 | 157 | ||
160 | sendmail->dsn = dsn; | ||
161 | |||
162 | switch (sendmail->state) | 158 | switch (sendmail->state) |
163 | { | 159 | { |
164 | case SENDMAIL_NO_STATE: | 160 | case SENDMAIL_NO_STATE: |
... | @@ -173,45 +169,6 @@ sendmail_send_message (mailer_t mailer, const char *from, const char *rcpt, | ... | @@ -173,45 +169,6 @@ sendmail_send_message (mailer_t mailer, const char *from, const char *rcpt, |
173 | argvec[1] = strdup ("-oi"); | 169 | argvec[1] = strdup ("-oi"); |
174 | argvec[2] = strdup ("-t"); | 170 | argvec[2] = strdup ("-t"); |
175 | 171 | ||
176 | if (from) | ||
177 | { | ||
178 | size_t len = strlen (from) + 1; | ||
179 | char *addr = calloc (len, sizeof (char)); | ||
180 | if (parseaddr (from, addr, len) == 0) | ||
181 | { | ||
182 | argc++; | ||
183 | argvec = realloc (argvec, argc * (sizeof (*argvec))); | ||
184 | argvec[argc - 1] = strdup ("-f"); | ||
185 | argc++; | ||
186 | argvec = realloc (argvec, argc * (sizeof (*argvec))); | ||
187 | argvec[argc - 1] = addr; | ||
188 | } | ||
189 | else | ||
190 | free (addr); | ||
191 | } | ||
192 | |||
193 | if (rcpt) | ||
194 | { | ||
195 | const char *p = rcpt; | ||
196 | do | ||
197 | { | ||
198 | size_t len = strlen (p) + 1; | ||
199 | char *addr = calloc (len, sizeof (char)); | ||
200 | if (parseaddr (rcpt, addr, len) == 0) | ||
201 | { | ||
202 | argc++; | ||
203 | argvec = realloc (argvec, argc * (sizeof (*argvec))); | ||
204 | argvec[argc - 1] = addr; | ||
205 | } | ||
206 | else | ||
207 | free (addr); | ||
208 | p = strchr (p, ','); | ||
209 | if (p != NULL) | ||
210 | p++; | ||
211 | } | ||
212 | while (p != NULL && *p != '\0'); | ||
213 | } | ||
214 | |||
215 | argc++; | 172 | argc++; |
216 | argvec = realloc (argvec, argc * (sizeof (*argvec))); | 173 | argvec = realloc (argvec, argc * (sizeof (*argvec))); |
217 | argvec[argc - 1] = NULL; | 174 | argvec[argc - 1] = NULL; | ... | ... |
... | @@ -29,6 +29,7 @@ | ... | @@ -29,6 +29,7 @@ |
29 | #include <netdb.h> | 29 | #include <netdb.h> |
30 | 30 | ||
31 | #include <mailutils/stream.h> | 31 | #include <mailutils/stream.h> |
32 | #include <mailutils/address.h> | ||
32 | #include <mailer0.h> | 33 | #include <mailer0.h> |
33 | #include <registrar0.h> | 34 | #include <registrar0.h> |
34 | #include <bio.h> | 35 | #include <bio.h> |
... | @@ -77,8 +78,9 @@ struct _smtp | ... | @@ -77,8 +78,9 @@ struct _smtp |
77 | SMTP_SEND_DOT | 78 | SMTP_SEND_DOT |
78 | } state; | 79 | } state; |
79 | int extended; | 80 | int extended; |
80 | char *from; | 81 | address_t mail_from; |
81 | char *to; | 82 | address_t rcpt_to; |
83 | size_t rcpt_index; | ||
82 | off_t offset; | 84 | off_t offset; |
83 | int dsn; | 85 | int dsn; |
84 | message_t message; | 86 | message_t message; |
... | @@ -133,13 +135,15 @@ while (0) | ... | @@ -133,13 +135,15 @@ while (0) |
133 | static void smtp_destroy (mailer_t); | 135 | static void smtp_destroy (mailer_t); |
134 | static int smtp_open (mailer_t, int); | 136 | static int smtp_open (mailer_t, int); |
135 | static int smtp_close (mailer_t); | 137 | static int smtp_close (mailer_t); |
136 | static int smtp_send_message (mailer_t, const char *from, const char *rcpt, | 138 | static int smtp_send_message (mailer_t, message_t); |
137 | int dsn, message_t); | ||
138 | static int smtp_writeline (smtp_t smtp, const char *format, ...); | 139 | static int smtp_writeline (smtp_t smtp, const char *format, ...); |
139 | static int smtp_readline (smtp_t); | 140 | static int smtp_readline (smtp_t); |
140 | static int smtp_read_ack (smtp_t); | 141 | static int smtp_read_ack (smtp_t); |
141 | static int smtp_write (smtp_t); | 142 | static int smtp_write (smtp_t); |
142 | 143 | ||
144 | static int get_rcpt (message_t , address_t *); | ||
145 | static int get_from (message_t , char *, address_t *); | ||
146 | |||
143 | int | 147 | int |
144 | smtp_init (mailer_t mailer) | 148 | smtp_init (mailer_t mailer) |
145 | { | 149 | { |
... | @@ -173,10 +177,10 @@ smtp_destroy(mailer_t mailer) | ... | @@ -173,10 +177,10 @@ smtp_destroy(mailer_t mailer) |
173 | bio_destroy (&(smtp->bio)); | 177 | bio_destroy (&(smtp->bio)); |
174 | if (smtp->buffer) | 178 | if (smtp->buffer) |
175 | free (smtp->buffer); | 179 | free (smtp->buffer); |
176 | if (smtp->from) | 180 | if (smtp->mail_from) |
177 | free (smtp->from); | 181 | address_destroy (&(smtp->mail_from)); |
178 | if (smtp->to) | 182 | if (smtp->rcpt_to) |
179 | free (smtp->to); | 183 | address_destroy (&(smtp->rcpt_to)); |
180 | free (smtp); | 184 | free (smtp); |
181 | mailer->data = NULL; | 185 | mailer->data = NULL; |
182 | } | 186 | } |
... | @@ -404,8 +408,7 @@ smtp_close (mailer_t mailer) | ... | @@ -404,8 +408,7 @@ smtp_close (mailer_t mailer) |
404 | } | 408 | } |
405 | 409 | ||
406 | static int | 410 | static int |
407 | smtp_send_message(mailer_t mailer, const char *from, const char *rcpt, | 411 | smtp_send_message(mailer_t mailer, message_t msg) |
408 | int dsn, message_t msg) | ||
409 | { | 412 | { |
410 | smtp_t smtp = mailer->data; | 413 | smtp_t smtp = mailer->data; |
411 | int status; | 414 | int status; |
... | @@ -416,127 +419,30 @@ smtp_send_message(mailer_t mailer, const char *from, const char *rcpt, | ... | @@ -416,127 +419,30 @@ smtp_send_message(mailer_t mailer, const char *from, const char *rcpt, |
416 | switch (smtp->state) | 419 | switch (smtp->state) |
417 | { | 420 | { |
418 | case SMTP_NO_STATE: | 421 | case SMTP_NO_STATE: |
419 | smtp->dsn = dsn; | ||
420 | smtp->state = SMTP_ENV_FROM; | 422 | smtp->state = SMTP_ENV_FROM; |
423 | status = get_from (msg, smtp->localhost, &smtp->mail_from); | ||
424 | CHECK_ERROR (smtp, status); | ||
425 | status = get_rcpt (msg, &smtp->rcpt_to); | ||
426 | CHECK_ERROR (smtp, status); | ||
421 | 427 | ||
422 | case SMTP_ENV_FROM: | 428 | case SMTP_ENV_FROM: |
423 | if (smtp->from) | ||
424 | { | 429 | { |
425 | free (smtp->from); | 430 | size_t len = 0; |
426 | smtp->from = NULL; | 431 | char *from; |
427 | } | 432 | address_get_email (smtp->mail_from, 1, NULL, 0, &len); |
428 | /* Try to fetch it from the header. */ | 433 | if (len == 0) |
434 | CHECK_ERROR (smtp, EINVAL); | ||
435 | from = calloc (len + 1, sizeof (char)); | ||
429 | if (from == NULL) | 436 | if (from == NULL) |
430 | { | ||
431 | header_t header; | ||
432 | size_t size; | ||
433 | message_get_header (msg, &header); | ||
434 | status = header_get_value (header, MU_HEADER_FROM, NULL, 0, &size); | ||
435 | if (status == EAGAIN) | ||
436 | return status; | ||
437 | /* If it's not in the header create one form the passwd. */ | ||
438 | if (status != 0) | ||
439 | { | ||
440 | struct passwd *pwd = getpwuid (getuid ()); | ||
441 | /* Not in the passwd ???? We have a problem. */ | ||
442 | if (pwd == 0 || pwd->pw_name == NULL) | ||
443 | { | ||
444 | size_t len = 10 + strlen (smtp->localhost) + 1; | ||
445 | smtp->from = calloc (len, sizeof (char)); | ||
446 | if (smtp->from == NULL) | ||
447 | { | ||
448 | CHECK_ERROR (smtp, ENOMEM); | ||
449 | } | ||
450 | snprintf (smtp->from, len, "%d@%s", getuid(), | ||
451 | smtp->localhost); | ||
452 | } | ||
453 | else | ||
454 | { | ||
455 | smtp->from = calloc (strlen (pwd->pw_name) + 1 | ||
456 | + strlen (smtp->localhost) + 1, | ||
457 | sizeof (char)); | ||
458 | if (smtp->from == NULL) | ||
459 | { | ||
460 | CHECK_ERROR (smtp, ENOMEM); | ||
461 | } | ||
462 | sprintf(smtp->from, "%s@%s", pwd->pw_name, smtp->localhost); | ||
463 | } | ||
464 | } | ||
465 | else | ||
466 | { | ||
467 | smtp->from = calloc (size + 1, sizeof (char)); | ||
468 | if (smtp->from == NULL) | ||
469 | { | ||
470 | CHECK_ERROR (smtp, ENOMEM); | ||
471 | } | ||
472 | status = header_get_value (header, MU_HEADER_FROM, smtp->from, | ||
473 | size + 1, NULL); | ||
474 | CHECK_EAGAIN (smtp, status); | ||
475 | } | ||
476 | } | ||
477 | else | ||
478 | { | ||
479 | smtp->from = strdup (from); | ||
480 | if (smtp->from == NULL) | ||
481 | { | ||
482 | CHECK_ERROR (smtp, ENOMEM); | 437 | CHECK_ERROR (smtp, ENOMEM); |
483 | } | 438 | address_get_email (smtp->mail_from, 1, from, len + 1, NULL); |
484 | } | 439 | status = smtp_writeline (smtp, "MAIL FROM: %s\r\n", from); |
485 | /* Check if a Fully Qualified Name, some smtp servers | 440 | free (from); |
486 | notably sendmail insists on it, for good reasons. */ | 441 | address_destroy (&smtp->mail_from); |
487 | if (strchr (smtp->from, '@') == NULL) | ||
488 | { | ||
489 | char *tmp; | ||
490 | tmp = malloc (strlen (smtp->from) + 1 +strlen (smtp->localhost) + 1); | ||
491 | if (tmp == NULL) | ||
492 | { | ||
493 | free (smtp->from); | ||
494 | smtp->from = NULL; | ||
495 | CHECK_ERROR (smtp, ENOMEM); | ||
496 | } | ||
497 | sprintf (tmp, "%s@%s", smtp->from, smtp->localhost); | ||
498 | free (smtp->from); | ||
499 | smtp->from = tmp; | ||
500 | } | ||
501 | smtp->state = SMTP_ENV_RCPT; | ||
502 | |||
503 | case SMTP_ENV_RCPT: | ||
504 | if (smtp->to) | ||
505 | { | ||
506 | free (smtp->to); | ||
507 | smtp->to = NULL; | ||
508 | } | ||
509 | if (rcpt == NULL) | ||
510 | { | ||
511 | header_t header; | ||
512 | size_t size; | ||
513 | message_get_header (msg, &header); | ||
514 | status = header_get_value (header, MU_HEADER_TO, NULL, 0, &size); | ||
515 | CHECK_EAGAIN (smtp, status); | ||
516 | smtp->to = calloc (size + 1, sizeof (char)); | ||
517 | if (smtp->to == NULL) | ||
518 | { | ||
519 | CHECK_ERROR (smtp, ENOMEM); | ||
520 | } | ||
521 | status = header_get_value (header, MU_HEADER_TO, smtp->to, | ||
522 | size + 1, NULL); | ||
523 | CHECK_EAGAIN (smtp, status); | ||
524 | } | ||
525 | else | ||
526 | { | ||
527 | smtp->to = strdup (rcpt); | ||
528 | if (smtp->to == NULL) | ||
529 | { | ||
530 | CHECK_ERROR (smtp, ENOMEM); | ||
531 | } | ||
532 | } | ||
533 | |||
534 | status = smtp_writeline (smtp, "MAIL FROM: %s\r\n", smtp->from); | ||
535 | free (smtp->from); | ||
536 | smtp->from = NULL; | ||
537 | CHECK_ERROR (smtp, status); | 442 | CHECK_ERROR (smtp, status); |
538 | MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); | 443 | MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); |
539 | smtp->state = SMTP_MAIL_FROM; | 444 | smtp->state = SMTP_MAIL_FROM; |
445 | } | ||
540 | 446 | ||
541 | case SMTP_MAIL_FROM: | 447 | case SMTP_MAIL_FROM: |
542 | status = smtp_write (smtp); | 448 | status = smtp_write (smtp); |
... | @@ -553,37 +459,51 @@ smtp_send_message(mailer_t mailer, const char *from, const char *rcpt, | ... | @@ -553,37 +459,51 @@ smtp_send_message(mailer_t mailer, const char *from, const char *rcpt, |
553 | CLEAR_STATE (smtp); | 459 | CLEAR_STATE (smtp); |
554 | return EACCES; | 460 | return EACCES; |
555 | } | 461 | } |
462 | |||
556 | /* We use a goto, since we may have multiple recipients, | 463 | /* We use a goto, since we may have multiple recipients, |
557 | we come back here and doit all over again ... Not pretty. */ | 464 | we come back here and doit all over again ... Not pretty. */ |
465 | case SMTP_ENV_RCPT: | ||
558 | RCPT_TO: | 466 | RCPT_TO: |
559 | { | 467 | { |
560 | char *buf; | 468 | size_t i = 0; |
561 | size_t len = strlen (smtp->to) + 1; | 469 | smtp->rcpt_index++; |
562 | buf = calloc (len, sizeof (char)); | 470 | address_get_count (smtp->rcpt_to, &i); |
563 | if (buf == NULL) | 471 | if (smtp->rcpt_index <= i) |
564 | { | ||
565 | CHECK_ERROR (smtp, ENOMEM); | ||
566 | } | ||
567 | if (parseaddr (smtp->to, buf, len) != 0) | ||
568 | { | 472 | { |
569 | free (buf); | 473 | size_t len = 0; |
474 | char *to; | ||
475 | address_get_email (smtp->rcpt_to, smtp->rcpt_index, NULL, 0, &len); | ||
476 | if (len == 0) | ||
570 | CHECK_ERROR (smtp, EINVAL); | 477 | CHECK_ERROR (smtp, EINVAL); |
571 | } | 478 | to = calloc (len + 1, sizeof (char)); |
572 | status = smtp_writeline (smtp, "RCPT TO: %s\r\n", buf); | 479 | if (to == NULL) |
573 | free (buf); | 480 | CHECK_ERROR (smtp, ENOMEM); |
481 | address_get_email (smtp->rcpt_to, smtp->rcpt_index, to, len + 1, NULL); | ||
482 | status = smtp_writeline (smtp, "RCPT TO: %s\r\n", to); | ||
483 | free (to); | ||
574 | CHECK_ERROR (smtp, status); | 484 | CHECK_ERROR (smtp, status); |
575 | MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); | 485 | MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); |
576 | smtp->state = SMTP_RCPT_TO; | 486 | smtp->state = SMTP_RCPT_TO; |
577 | } | 487 | } |
488 | else | ||
489 | { | ||
490 | address_destroy (&(smtp->rcpt_to)); | ||
491 | smtp->rcpt_index = 0; | ||
492 | smtp->state = SMTP_DATA; | ||
493 | } | ||
494 | } | ||
578 | 495 | ||
579 | case SMTP_RCPT_TO: | 496 | case SMTP_RCPT_TO: |
497 | if (smtp->rcpt_to) | ||
498 | { | ||
580 | status = smtp_write (smtp); | 499 | status = smtp_write (smtp); |
581 | CHECK_EAGAIN (smtp, status); | 500 | CHECK_EAGAIN (smtp, status); |
582 | smtp->state = SMTP_RCPT_TO_ACK; | 501 | smtp->state = SMTP_RCPT_TO_ACK; |
502 | } | ||
583 | 503 | ||
584 | case SMTP_RCPT_TO_ACK: | 504 | case SMTP_RCPT_TO_ACK: |
505 | if (smtp->rcpt_to) | ||
585 | { | 506 | { |
586 | char *p; | ||
587 | status = smtp_read_ack (smtp); | 507 | status = smtp_read_ack (smtp); |
588 | CHECK_EAGAIN (smtp, status); | 508 | CHECK_EAGAIN (smtp, status); |
589 | MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); | 509 | MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); |
... | @@ -593,28 +513,13 @@ smtp_send_message(mailer_t mailer, const char *from, const char *rcpt, | ... | @@ -593,28 +513,13 @@ smtp_send_message(mailer_t mailer, const char *from, const char *rcpt, |
593 | CLEAR_STATE (smtp); | 513 | CLEAR_STATE (smtp); |
594 | return EACCES; | 514 | return EACCES; |
595 | } | 515 | } |
596 | /* Do we have multiple recipients ? */ | ||
597 | p = strchr (smtp->to, ','); | ||
598 | if (p != NULL) | ||
599 | { | ||
600 | char *tmp = smtp->to; | ||
601 | smtp->to = strdup (p++); | ||
602 | if (smtp->to == NULL) | ||
603 | { | ||
604 | free (tmp); | ||
605 | CHECK_ERROR (smtp, ENOMEM); | ||
606 | } | ||
607 | free (tmp); | ||
608 | goto RCPT_TO; | 516 | goto RCPT_TO; |
609 | } | 517 | } |
610 | /* We are done with the rcpt. */ | 518 | /* We are done with the rcpt. */ |
611 | free (smtp->to); | ||
612 | smtp->to = NULL; | ||
613 | status = smtp_writeline (smtp, "DATA\r\n"); | 519 | status = smtp_writeline (smtp, "DATA\r\n"); |
614 | CHECK_ERROR (smtp, status); | 520 | CHECK_ERROR (smtp, status); |
615 | MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); | 521 | MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); |
616 | smtp->state = SMTP_DATA; | 522 | smtp->state = SMTP_DATA; |
617 | } | ||
618 | 523 | ||
619 | case SMTP_DATA: | 524 | case SMTP_DATA: |
620 | status = smtp_write (smtp); | 525 | status = smtp_write (smtp); |
... | @@ -693,6 +598,125 @@ smtp_send_message(mailer_t mailer, const char *from, const char *rcpt, | ... | @@ -693,6 +598,125 @@ smtp_send_message(mailer_t mailer, const char *from, const char *rcpt, |
693 | } | 598 | } |
694 | 599 | ||
695 | static int | 600 | static int |
601 | get_from (message_t msg, char *localhost, address_t *pmail_from) | ||
602 | { | ||
603 | int status; | ||
604 | size_t size = 0; | ||
605 | char *from; | ||
606 | header_t header = NULL; | ||
607 | |||
608 | message_get_header (msg, &header); | ||
609 | status = header_get_value (header, MU_HEADER_FROM, NULL, 0, &size); | ||
610 | /* If it's not in the header create one form the passwd. */ | ||
611 | if (status != 0 || size == 0) | ||
612 | { | ||
613 | struct passwd *pwd = getpwuid (getuid ()); | ||
614 | /* Not in the passwd ???? We have a problem. */ | ||
615 | if (pwd == 0 || pwd->pw_name == NULL) | ||
616 | { | ||
617 | size = 10 + strlen (localhost) + 1; | ||
618 | from = calloc (size, sizeof (char)); | ||
619 | if (from == NULL) | ||
620 | return ENOMEM; | ||
621 | snprintf (from, size, "%d@%s", getuid(), localhost); | ||
622 | } | ||
623 | else | ||
624 | { | ||
625 | from = calloc (strlen (pwd->pw_name) + 1 | ||
626 | + strlen (localhost) + 1, sizeof (char)); | ||
627 | if (from == NULL) | ||
628 | return ENOMEM; | ||
629 | sprintf(from, "%s@%s", pwd->pw_name, localhost); | ||
630 | } | ||
631 | } | ||
632 | else | ||
633 | { | ||
634 | from = calloc (size + 1, sizeof (char)); | ||
635 | if (from == NULL) | ||
636 | return ENOMEM; | ||
637 | header_get_value (header, MU_HEADER_FROM, from, size + 1, NULL); | ||
638 | } | ||
639 | /* Check if a Fully Qualified Name, some smtp servers | ||
640 | notably sendmail insists on it, for good reasons. */ | ||
641 | if (strchr (from, '@') == NULL) | ||
642 | { | ||
643 | char *tmp; | ||
644 | tmp = malloc (strlen (from) + 1 +strlen (localhost) + 1); | ||
645 | if (tmp == NULL) | ||
646 | { | ||
647 | free (from); | ||
648 | return ENOMEM; | ||
649 | } | ||
650 | sprintf (tmp, "%s@%s", from, localhost); | ||
651 | free (from); | ||
652 | from = tmp; | ||
653 | } | ||
654 | status = address_create (pmail_from, from); | ||
655 | free (from); | ||
656 | return status; | ||
657 | } | ||
658 | |||
659 | static int | ||
660 | get_rcpt (message_t msg, address_t *prcpt_to) | ||
661 | { | ||
662 | char *rcpt; | ||
663 | int status; | ||
664 | size_t size = 0; | ||
665 | header_t header = NULL; | ||
666 | |||
667 | message_get_header (msg, &header); | ||
668 | status = header_get_value (header, MU_HEADER_TO, NULL, 0, &size); | ||
669 | if (status == 0 && size != 0) | ||
670 | { | ||
671 | char *tmp; | ||
672 | size_t len; | ||
673 | rcpt = calloc (size + 1, sizeof (char)); | ||
674 | if (rcpt == NULL) | ||
675 | return ENOMEM; | ||
676 | header_get_value (header, MU_HEADER_TO, rcpt, size + 1, NULL); | ||
677 | |||
678 | size = 0; | ||
679 | status = header_get_value (header, MU_HEADER_CC, NULL, 0, &size); | ||
680 | if (status == 0 && size != 0) | ||
681 | { | ||
682 | len = strlen (rcpt); | ||
683 | tmp = realloc (rcpt, (len + 1 + size + 1) * sizeof (char)); | ||
684 | if (tmp == NULL) | ||
685 | { | ||
686 | free (rcpt); | ||
687 | return ENOMEM; | ||
688 | } | ||
689 | else | ||
690 | rcpt = tmp; | ||
691 | rcpt[len] = ','; | ||
692 | header_get_value (header, MU_HEADER_CC, rcpt + len + 1, | ||
693 | size + 1, NULL); | ||
694 | |||
695 | size = 0; | ||
696 | status = header_get_value (header, MU_HEADER_BCC, NULL, 0, &size); | ||
697 | if (status == 0 && size != 0) | ||
698 | { | ||
699 | len = strlen (rcpt); | ||
700 | tmp = realloc (rcpt, (len + 1 + size + 1) * sizeof (char)); | ||
701 | if (tmp == NULL) | ||
702 | { | ||
703 | free (rcpt); | ||
704 | return ENOMEM; | ||
705 | } | ||
706 | else | ||
707 | rcpt = tmp; | ||
708 | rcpt[len] = ','; | ||
709 | header_get_value (header, MU_HEADER_BCC, rcpt + len + 1, | ||
710 | size + 1, NULL); | ||
711 | } | ||
712 | } | ||
713 | status = address_create (prcpt_to, rcpt); | ||
714 | free (rcpt); | ||
715 | return status; | ||
716 | } | ||
717 | return EINVAL; | ||
718 | } | ||
719 | static int | ||
696 | smtp_writeline (smtp_t smtp, const char *format, ...) | 720 | smtp_writeline (smtp_t smtp, const char *format, ...) |
697 | { | 721 | { |
698 | int len; | 722 | int len; | ... | ... |
-
Please register or sign in to post a comment