Commit 1c21c97f 1c21c97fb9b01a50a5d812a55345787045f73f91 by Sam Roberts

Implemented correct semantics for sending mail to bcc'ed addresses.

1 parent 026e47c0
...@@ -70,16 +70,18 @@ struct _mailer ...@@ -70,16 +70,18 @@ struct _mailer
70 if (mailer->observer) observer_notify (mailer->observer, type) 70 if (mailer->observer) observer_notify (mailer->observer, type)
71 71
72 /* Moro(?)ic kluge. */ 72 /* Moro(?)ic kluge. */
73 #define MAILER_DEBUGV(mailer, type, format, av) \
74 if (mailer->debug) mu_debug_print (mailer->debug, type, format, av)
73 #define MAILER_DEBUG0(mailer, type, format) \ 75 #define MAILER_DEBUG0(mailer, type, format) \
74 if (mailer->debug) mu_debug_print (mailer->debug, type, format) 76 if (mailer->debug) mu_debug_print (mailer->debug, type, format)
75 #define MAILER_DEBUG1(mailer, type, format, arg1) \ 77 #define MAILER_DEBUG1(mailer, type, format, arg1) \
76 if (mailer->debug) mu_debug_print (mailer->debug, type, format, arg1) 78 if (mailer->debug) mu_debug_print (mailer->debug, type, format, arg1)
77 #define MAILER_DEBUG2(mailer, type, format, arg1, arg2) \ 79 #define MAILER_DEBUG2(mailer, type, format, arg1, arg2) \
78 if (mailer->debug) mu_debug_print (mailer->debug, type, format, arg1, arg2) 80 if (mailer->debug) mu_debug_print (mailer->debug, type, format, arg1, arg2)
79 #define MAILER_DEBUG3(mailer, type, format, arg1, arg2, arg3) \ 81 #define MAILER_DEBUG3(mailer, type, format, arg1, arg2, arg3) \
80 if (mailer->debug) mu_debug_print (mailer->debug, type, format, arg1, arg2, arg3) 82 if (mailer->debug) mu_debug_print (mailer->debug, type, format, arg1, arg2, arg3)
81 #define MAILER_DEBUG4(mailer, type, format, arg1, arg2, arg3, arg4) \ 83 #define MAILER_DEBUG4(mailer, type, format, arg1, arg2, arg3, arg4) \
82 if (mailer->debug) mu_debug_print (mailer->debug, type, format, arg1, arg2, arg3, arg4) 84 if (mailer->debug) mu_debug_print (mailer->debug, type, format, arg1, arg2, arg3, arg4)
83 85
84 #ifdef __cplusplus 86 #ifdef __cplusplus
85 } 87 }
......
...@@ -19,7 +19,9 @@ ...@@ -19,7 +19,9 @@
19 # include <config.h> 19 # include <config.h>
20 #endif 20 #endif
21 21
22 #include <assert.h>
22 #include <errno.h> 23 #include <errno.h>
24 #include <ctype.h>
23 #include <netdb.h> 25 #include <netdb.h>
24 #include <pwd.h> 26 #include <pwd.h>
25 #include <stdarg.h> 27 #include <stdarg.h>
...@@ -30,6 +32,7 @@ ...@@ -30,6 +32,7 @@
30 32
31 #include <mailutils/address.h> 33 #include <mailutils/address.h>
32 #include <mailutils/debug.h> 34 #include <mailutils/debug.h>
35 #include <mailutils/errno.h>
33 #include <mailutils/header.h> 36 #include <mailutils/header.h>
34 #include <mailutils/message.h> 37 #include <mailutils/message.h>
35 #include <mailutils/mutil.h> 38 #include <mailutils/mutil.h>
...@@ -65,11 +68,12 @@ struct _smtp ...@@ -65,11 +68,12 @@ struct _smtp
65 char *mailhost; 68 char *mailhost;
66 char *localhost; 69 char *localhost;
67 70
68 /* Buffered the IO. */ 71 /* IO buffering. */
72 char *buffer; /* Must be freed. */
73 size_t buflen;
74
69 char *ptr; 75 char *ptr;
70 char *nl; 76 char *nl;
71 char *buffer;
72 size_t buflen;
73 off_t s_offset; 77 off_t s_offset;
74 78
75 enum smtp_state 79 enum smtp_state
...@@ -83,22 +87,95 @@ struct _smtp ...@@ -83,22 +87,95 @@ struct _smtp
83 87
84 int extended; 88 int extended;
85 89
86 address_t mail_from; 90 char* mail_from;
87 address_t rcpt_to; 91 address_t rcpt_to; /* Destroy this if not the same as TO below. */
92 address_t rcpt_bcc;
93 size_t rcpt_to_count;
94 size_t rcpt_bcc_count;
88 size_t rcpt_index; 95 size_t rcpt_index;
96 size_t rcpt_count;
97 int bccing;
98 message_t msg;
89 99
90 off_t offset; 100 off_t offset;
91 int dsn; 101
92 message_t message; 102 /* The mailer_send_message() args. */
103 message_t argmsg;
104 address_t argfrom;
105 address_t argto;
93 }; 106 };
94 107
95 typedef struct _smtp * smtp_t; 108 typedef struct _smtp * smtp_t;
96 109
97 /* Usefull little Macros, since these are very repetitive. */ 110 /* Useful little macros, since these are very repetitive. */
98 #define CLEAR_STATE(smtp) \ 111
99 smtp->state = SMTP_NO_STATE 112 static void
113 CLEAR_STATE (smtp_t smtp)
114 {
115 smtp->ptr = NULL;
116 smtp->nl = NULL;
117 smtp->s_offset = 0;
118 smtp->extended = 0;
119
120 smtp->msg = NULL;
121
122 if (smtp->mail_from)
123 {
124 free (smtp->mail_from);
125 smtp->mail_from = NULL;
126 }
127
128 smtp->argfrom = NULL;
129
130 if (smtp->rcpt_to != smtp->argto)
131 address_destroy (&smtp->rcpt_to);
132
133 address_destroy (&smtp->rcpt_bcc);
134
135 if (smtp->msg != smtp->argmsg)
136 message_destroy (&smtp->msg, NULL);
137
138 smtp->argmsg = smtp->msg = NULL;
139
140 smtp->rcpt_to = smtp->argto = NULL;
100 141
101 /* Clear the state and close the stream. */ 142 smtp->rcpt_index = 0;
143
144 smtp->offset = 0;
145
146 smtp->state = SMTP_NO_STATE;
147 }
148
149 /* If we are resuming, we should be resuming the SAME operation
150 as that which is ongoing. Check this. */
151 static int
152 smtp_check_send_resumption (smtp_t smtp,
153 message_t msg, address_t from, address_t to)
154 {
155 if(smtp->state == SMTP_NO_STATE)
156 return 0;
157
158 /* FIXME: state should be one of the "send" states if its not
159 "no state" */
160 if (msg != smtp->argmsg)
161 return MU_ERR_BAD_RESUMPTION;
162
163 if (from != smtp->argfrom)
164 return MU_ERR_BAD_RESUMPTION;
165
166 if (to != smtp->argto)
167 return MU_ERR_BAD_RESUMPTION;
168
169 return 0;
170 }
171
172 #define CHECK_SEND_RESUME(smtp, msg, from, to) \
173 do { \
174 if((status = smtp_check_send_resumption(smtp, msg, from, to)) != 0) \
175 return status; \
176 } while (0)
177
178 /* Clear the state and close the stream. */
102 #define CHECK_ERROR_CLOSE(mailer, smtp, status) \ 179 #define CHECK_ERROR_CLOSE(mailer, smtp, status) \
103 do \ 180 do \
104 { \ 181 { \
...@@ -111,7 +188,7 @@ do \ ...@@ -111,7 +188,7 @@ do \
111 } \ 188 } \
112 while (0) 189 while (0)
113 190
114 /* Clear the state. */ 191 /* Clear the state. */
115 #define CHECK_ERROR(smtp, status) \ 192 #define CHECK_ERROR(smtp, status) \
116 do \ 193 do \
117 { \ 194 { \
...@@ -147,8 +224,8 @@ static int smtp_readline (smtp_t); ...@@ -147,8 +224,8 @@ static int smtp_readline (smtp_t);
147 static int smtp_read_ack (smtp_t); 224 static int smtp_read_ack (smtp_t);
148 static int smtp_write (smtp_t); 225 static int smtp_write (smtp_t);
149 226
150 static int get_rcpt (message_t , address_t *); 227 static int _smtp_set_from (smtp_t, message_t , address_t);
151 static int get_from (message_t , char *, address_t *); 228 static int _smtp_set_rcpt (smtp_t, message_t , address_t);
152 229
153 int 230 int
154 _mailer_smtp_init (mailer_t mailer) 231 _mailer_smtp_init (mailer_t mailer)
...@@ -182,19 +259,20 @@ static void ...@@ -182,19 +259,20 @@ static void
182 smtp_destroy(mailer_t mailer) 259 smtp_destroy(mailer_t mailer)
183 { 260 {
184 smtp_t smtp = mailer->data; 261 smtp_t smtp = mailer->data;
262
263 CLEAR_STATE(smtp);
264
185 /* Not our responsability to close. */ 265 /* Not our responsability to close. */
186 /* smtp_close (mailer); */ 266
187 if (smtp->mailhost) 267 if (smtp->mailhost)
188 free (smtp->mailhost); 268 free (smtp->mailhost);
189 if (smtp->localhost) 269 if (smtp->localhost)
190 free (smtp->localhost); 270 free (smtp->localhost);
191 if (smtp->buffer) 271 if (smtp->buffer)
192 free (smtp->buffer); 272 free (smtp->buffer);
193 if (smtp->mail_from) 273
194 address_destroy (&(smtp->mail_from));
195 if (smtp->rcpt_to)
196 address_destroy (&(smtp->rcpt_to));
197 free (smtp); 274 free (smtp);
275
198 mailer->data = NULL; 276 mailer->data = NULL;
199 } 277 }
200 278
...@@ -207,8 +285,7 @@ smtp_open (mailer_t mailer, int flags) ...@@ -207,8 +285,7 @@ smtp_open (mailer_t mailer, int flags)
207 size_t buf_len = 0; 285 size_t buf_len = 0;
208 286
209 /* Sanity checks. */ 287 /* Sanity checks. */
210 if (smtp == NULL) 288 assert (smtp);
211 return EINVAL;
212 289
213 mailer->flags = flags; 290 mailer->flags = flags;
214 291
...@@ -220,6 +297,7 @@ smtp_open (mailer_t mailer, int flags) ...@@ -220,6 +297,7 @@ smtp_open (mailer_t mailer, int flags)
220 switch (smtp->state) 297 switch (smtp->state)
221 { 298 {
222 case SMTP_NO_STATE: 299 case SMTP_NO_STATE:
300 /* Set up the mailer, open the stream, etc. */
223 /* Get the mailhost. */ 301 /* Get the mailhost. */
224 if (smtp->mailhost) 302 if (smtp->mailhost)
225 { 303 {
...@@ -227,8 +305,10 @@ smtp_open (mailer_t mailer, int flags) ...@@ -227,8 +305,10 @@ smtp_open (mailer_t mailer, int flags)
227 smtp->mailhost = NULL; 305 smtp->mailhost = NULL;
228 } 306 }
229 smtp->mailhost = calloc (buf_len + 1, sizeof (char)); 307 smtp->mailhost = calloc (buf_len + 1, sizeof (char));
308
230 if (smtp->mailhost == NULL) 309 if (smtp->mailhost == NULL)
231 return ENOMEM; 310 return ENOMEM;
311
232 url_get_host (mailer->url, smtp->mailhost, buf_len + 1, NULL); 312 url_get_host (mailer->url, smtp->mailhost, buf_len + 1, NULL);
233 313
234 if (smtp->localhost) 314 if (smtp->localhost)
...@@ -236,63 +316,16 @@ smtp_open (mailer_t mailer, int flags) ...@@ -236,63 +316,16 @@ smtp_open (mailer_t mailer, int flags)
236 free (smtp->localhost); 316 free (smtp->localhost);
237 smtp->localhost = NULL; 317 smtp->localhost = NULL;
238 } 318 }
239 /* Fetch our localhost name. */ 319 /* Fetch our local host name. */
240 buf_len = 64; 320
241 do 321 status = mu_get_host_name(&smtp->localhost);
242 { 322
243 char *tmp; 323 if (status != 0)
244 errno = 0;
245 buf_len *= 2; /* Initial guess */
246 tmp = realloc (smtp->localhost, buf_len);
247 if (tmp == NULL)
248 {
249 if (smtp->localhost)
250 free (smtp->localhost);
251 smtp->localhost = NULL;
252 free (smtp->mailhost);
253 smtp->mailhost = NULL;
254 return ENOMEM;
255 }
256 smtp->localhost = tmp;
257 }
258 while (((status = gethostname(smtp->localhost, buf_len)) == 0
259 && !memchr (smtp->localhost, '\0', buf_len))
260 #ifdef ENAMETOOLONG
261 || errno == ENAMETOOLONG
262 #endif
263 );
264 if (status != 0 && errno != 0)
265 { 324 {
266 /* gethostname failed, abort. */ 325 /* gethostname failed, abort. */
267 free (smtp->localhost);
268 smtp->localhost = NULL;
269 free (smtp->mailhost); 326 free (smtp->mailhost);
270 smtp->mailhost = NULL; 327 smtp->mailhost = NULL;
271 return EINVAL; 328 return status;
272 }
273
274 /* Many SMTP servers prefer a FQDN. */
275 if (strchr (smtp->localhost, '.') == NULL)
276 {
277 struct hostent *hp = gethostbyname (smtp->localhost);
278 if (hp == NULL)
279 {
280 /* Don't flag it as an error some SMTP servers can get the FQDN
281 by themselves even if the client is lying, probably
282 with getpeername(). */
283 /* return EINVAL; */
284 }
285 else
286 {
287 free (smtp->localhost);
288 smtp->localhost = strdup (hp->h_name);
289 if (smtp->localhost == NULL)
290 {
291 free (smtp->mailhost);
292 smtp->mailhost = NULL;
293 return ENOMEM;
294 }
295 }
296 } 329 }
297 330
298 /* allocate a working io buffer. */ 331 /* allocate a working io buffer. */
...@@ -318,7 +351,7 @@ smtp_open (mailer_t mailer, int flags) ...@@ -318,7 +351,7 @@ smtp_open (mailer_t mailer, int flags)
318 smtp->state = SMTP_OPEN; 351 smtp->state = SMTP_OPEN;
319 352
320 case SMTP_OPEN: 353 case SMTP_OPEN:
321 MAILER_DEBUG2 (mailer, MU_DEBUG_PROT, "smtp_open (%s:%d)\n", 354 MAILER_DEBUG2 (mailer, MU_DEBUG_PROT, "smtp_open (host: %s port: %d)\n",
322 smtp->mailhost, port); 355 smtp->mailhost, port);
323 status = stream_open (mailer->stream); 356 status = stream_open (mailer->stream);
324 CHECK_EAGAIN (smtp, status); 357 CHECK_EAGAIN (smtp, status);
...@@ -328,7 +361,7 @@ smtp_open (mailer_t mailer, int flags) ...@@ -328,7 +361,7 @@ smtp_open (mailer_t mailer, int flags)
328 /* Swallow the greetings. */ 361 /* Swallow the greetings. */
329 status = smtp_read_ack (smtp); 362 status = smtp_read_ack (smtp);
330 CHECK_EAGAIN (smtp, status); 363 CHECK_EAGAIN (smtp, status);
331 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); 364
332 if (smtp->buffer[0] != '2') 365 if (smtp->buffer[0] != '2')
333 { 366 {
334 stream_close (mailer->stream); 367 stream_close (mailer->stream);
...@@ -336,7 +369,7 @@ smtp_open (mailer_t mailer, int flags) ...@@ -336,7 +369,7 @@ smtp_open (mailer_t mailer, int flags)
336 } 369 }
337 status = smtp_writeline (smtp, "EHLO %s\r\n", smtp->localhost); 370 status = smtp_writeline (smtp, "EHLO %s\r\n", smtp->localhost);
338 CHECK_ERROR (smtp, status); 371 CHECK_ERROR (smtp, status);
339 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); 372
340 smtp->state = SMTP_EHLO; 373 smtp->state = SMTP_EHLO;
341 374
342 case SMTP_EHLO: 375 case SMTP_EHLO:
...@@ -348,7 +381,7 @@ smtp_open (mailer_t mailer, int flags) ...@@ -348,7 +381,7 @@ smtp_open (mailer_t mailer, int flags)
348 case SMTP_EHLO_ACK: 381 case SMTP_EHLO_ACK:
349 status = smtp_read_ack (smtp); 382 status = smtp_read_ack (smtp);
350 CHECK_EAGAIN (smtp, status); 383 CHECK_EAGAIN (smtp, status);
351 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); 384
352 if (smtp->buffer[0] != '2') 385 if (smtp->buffer[0] != '2')
353 { 386 {
354 smtp->extended = 0; 387 smtp->extended = 0;
...@@ -363,7 +396,7 @@ smtp_open (mailer_t mailer, int flags) ...@@ -363,7 +396,7 @@ smtp_open (mailer_t mailer, int flags)
363 } 396 }
364 397
365 case SMTP_HELO: 398 case SMTP_HELO:
366 if (!smtp->extended) 399 if (!smtp->extended) /* FIXME: this will always be false! */
367 { 400 {
368 status = smtp_write (smtp); 401 status = smtp_write (smtp);
369 CHECK_EAGAIN (smtp, status); 402 CHECK_EAGAIN (smtp, status);
...@@ -375,7 +408,7 @@ smtp_open (mailer_t mailer, int flags) ...@@ -375,7 +408,7 @@ smtp_open (mailer_t mailer, int flags)
375 { 408 {
376 status = smtp_read_ack (smtp); 409 status = smtp_read_ack (smtp);
377 CHECK_EAGAIN (smtp, status); 410 CHECK_EAGAIN (smtp, status);
378 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); 411
379 if (smtp->buffer[0] != '2') 412 if (smtp->buffer[0] != '2')
380 { 413 {
381 stream_close (mailer->stream); 414 stream_close (mailer->stream);
...@@ -399,9 +432,9 @@ smtp_close (mailer_t mailer) ...@@ -399,9 +432,9 @@ smtp_close (mailer_t mailer)
399 switch (smtp->state) 432 switch (smtp->state)
400 { 433 {
401 case SMTP_NO_STATE: 434 case SMTP_NO_STATE:
402 status = smtp_writeline (smtp, "Quit\r\n"); 435 status = smtp_writeline (smtp, "QUIT\r\n");
403 CHECK_ERROR (smtp, status); 436 CHECK_ERROR (smtp, status);
404 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); 437
405 smtp->state = SMTP_QUIT; 438 smtp->state = SMTP_QUIT;
406 439
407 case SMTP_QUIT: 440 case SMTP_QUIT:
...@@ -412,7 +445,6 @@ smtp_close (mailer_t mailer) ...@@ -412,7 +445,6 @@ smtp_close (mailer_t mailer)
412 case SMTP_QUIT_ACK: 445 case SMTP_QUIT_ACK:
413 status = smtp_read_ack (smtp); 446 status = smtp_read_ack (smtp);
414 CHECK_EAGAIN (smtp, status); 447 CHECK_EAGAIN (smtp, status);
415 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer);
416 448
417 default: 449 default:
418 break; 450 break;
...@@ -421,46 +453,119 @@ smtp_close (mailer_t mailer) ...@@ -421,46 +453,119 @@ smtp_close (mailer_t mailer)
421 } 453 }
422 454
423 static int 455 static int
424 smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to) 456 message_set_header_value (message_t msg, const char *field, const char *value)
425 { 457 {
426 smtp_t smtp = mailer->data; 458 int status = 0;
459 header_t hdr = NULL;
460
461 if ((status = message_get_header (msg, &hdr)))
462 return status;
463
464 if ((status = header_set_value (hdr, field, value, 1)))
465 return status;
466
467 return status;
468 }
469
470 /*
471
472 The smtp mailer doesn't deal with mail like:
473
474 To: public@com, pub2@com
475 Bcc: hidden@there, two@there
476
477 It just sends the message to all the addresses, making the
478 "blind" cc not particularly blind.
479
480 The correct algorithm is
481
482 - open smtp connection
483 - look as msg, figure out addrto&cc, and addrbcc
484 - deliver to the to & cc addresses:
485 - if there are bcc addrs, remove the bcc field
486 - send the message to to & cc addrs:
487 mail from: me
488 rcpt to: public@com
489 rcpt to: pub2@com
490 data
491 ...
492
493 - deliver to the bcc addrs:
494
495 for a in (bccaddrs)
496 do
497 - add header field to msg, bcc: $a
498 - send the msg:
499 mail from: me
500 rcpt to: $a
501 data
502 ...
503 done
504
505 - quit smtp connection
506
507 */
508
509 static int
510 smtp_send_message (mailer_t mailer, message_t argmsg, address_t argfrom,
511 address_t argto)
512 {
513 smtp_t smtp = NULL;
427 int status; 514 int status;
428 515
429 if (smtp == NULL || msg == NULL) 516 if(mailer == NULL)
430 return EINVAL; 517 return EINVAL;
431 518
432 /* FIXME: implement the from and to */ 519 smtp = mailer->data;
433 if(from || to) 520 assert (smtp);
434 return ENOSYS; 521
522 CHECK_SEND_RESUME (smtp, argmsg, argfrom, argto);
435 523
436 switch (smtp->state) 524 switch (smtp->state)
437 { 525 {
438 case SMTP_NO_STATE: 526 case SMTP_NO_STATE:
439 smtp->state = SMTP_ENV_FROM; 527 if (argmsg == NULL)
440 status = get_from (msg, smtp->localhost, &smtp->mail_from); 528 return EINVAL;
529
530 smtp->argmsg = smtp->msg = argmsg;
531 smtp->argfrom = argfrom;
532 smtp->argto = argto;
533
534 status = _smtp_set_from (smtp, smtp->argmsg, smtp->argfrom);
441 CHECK_ERROR (smtp, status); 535 CHECK_ERROR (smtp, status);
442 status = get_rcpt (msg, &smtp->rcpt_to); 536
537 status = _smtp_set_rcpt (smtp, smtp->argmsg, smtp->argto);
443 CHECK_ERROR (smtp, status); 538 CHECK_ERROR (smtp, status);
444 539
540 /* Clear the Bcc: field if we found one. */
541 if (smtp->rcpt_bcc)
542 {
543 smtp->msg = NULL;
544 status = message_create_copy (&smtp->msg, smtp->argmsg);
545 CHECK_ERROR (smtp, status);
546
547 status = message_set_header_value (smtp->msg, MU_HEADER_BCC, NULL);
548 CHECK_ERROR (smtp, status);
549 }
550
551 /* Begin bccing if there are not To: recipients. */
552 if (smtp->rcpt_to_count == 0)
553 smtp->bccing = 1;
554
555 smtp->rcpt_index = 1;
556
557 smtp->state = SMTP_ENV_FROM;
558
445 case SMTP_ENV_FROM: 559 case SMTP_ENV_FROM:
560 ENV_FROM:
446 { 561 {
447 size_t len = 0; 562 status = smtp_writeline (smtp, "MAIL FROM: %s\r\n", smtp->mail_from);
448 char *frm;
449 address_get_email (smtp->mail_from, 1, NULL, 0, &len);
450 if (len == 0)
451 CHECK_ERROR (smtp, EINVAL);
452 frm = calloc (len + 1, sizeof (char));
453 if (frm == NULL)
454 CHECK_ERROR (smtp, ENOMEM);
455 address_get_email (smtp->mail_from, 1, frm, len + 1, NULL);
456 status = smtp_writeline (smtp, "MAIL FROM: %s\r\n", frm);
457 free (frm);
458 address_destroy (&smtp->mail_from);
459 CHECK_ERROR (smtp, status); 563 CHECK_ERROR (smtp, status);
460 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer);
461 smtp->state = SMTP_MAIL_FROM; 564 smtp->state = SMTP_MAIL_FROM;
462 } 565 }
463 566
567 /* We use a goto, since we may have multiple messages,
568 we come back here and doit all over again ... Not pretty. */
464 case SMTP_MAIL_FROM: 569 case SMTP_MAIL_FROM:
465 status = smtp_write (smtp); 570 status = smtp_write (smtp);
466 CHECK_EAGAIN (smtp, status); 571 CHECK_EAGAIN (smtp, status);
...@@ -469,7 +574,6 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to) ...@@ -469,7 +574,6 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to)
469 case SMTP_MAIL_FROM_ACK: 574 case SMTP_MAIL_FROM_ACK:
470 status = smtp_read_ack (smtp); 575 status = smtp_read_ack (smtp);
471 CHECK_EAGAIN (smtp, status); 576 CHECK_EAGAIN (smtp, status);
472 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer);
473 if (smtp->buffer[0] != '2') 577 if (smtp->buffer[0] != '2')
474 { 578 {
475 stream_close (mailer->stream); 579 stream_close (mailer->stream);
...@@ -478,64 +582,58 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to) ...@@ -478,64 +582,58 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to)
478 } 582 }
479 583
480 /* We use a goto, since we may have multiple recipients, 584 /* We use a goto, since we may have multiple recipients,
481 we come back here and doit all over again ... Not pretty. */ 585 we come back here and do it all over again ... Not pretty. */
482 case SMTP_ENV_RCPT: 586 case SMTP_ENV_RCPT:
483 RCPT_TO: 587 ENV_RCPT:
484 { 588 {
485 size_t i = 0; 589 address_t addr = smtp->rcpt_to;
590 char *to = NULL;
591
592 if (smtp->bccing)
593 addr = smtp->rcpt_bcc;
594
595 status = address_aget_email (addr, smtp->rcpt_index, &to);
596
597 CHECK_ERROR (smtp, status);
598
599 /* Add the Bcc: field back in for recipient. */
600 if(smtp->bccing)
601 {
602 status = message_set_header_value (smtp->msg, MU_HEADER_BCC, to);
603 CHECK_ERROR (smtp, status);
604 }
605
606 status = smtp_writeline (smtp, "RCPT TO: %s\r\n", to);
607
608 free (to);
609
610 CHECK_ERROR (smtp, status);
611
612 smtp->state = SMTP_RCPT_TO;
486 smtp->rcpt_index++; 613 smtp->rcpt_index++;
487 address_get_count (smtp->rcpt_to, &i);
488 if (smtp->rcpt_index <= i)
489 {
490 size_t len = 0;
491 char *To;
492 address_get_email (smtp->rcpt_to, smtp->rcpt_index, NULL, 0, &len);
493 if (len == 0)
494 CHECK_ERROR (smtp, EINVAL);
495 To = calloc (len + 1, sizeof (char));
496 if (To == NULL)
497 CHECK_ERROR (smtp, ENOMEM);
498 address_get_email (smtp->rcpt_to, smtp->rcpt_index, To, len + 1, NULL);
499 status = smtp_writeline (smtp, "RCPT TO: %s\r\n", To);
500 free (To);
501 CHECK_ERROR (smtp, status);
502 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer);
503 smtp->state = SMTP_RCPT_TO;
504 }
505 else
506 {
507 address_destroy (&(smtp->rcpt_to));
508 smtp->rcpt_index = 0;
509 smtp->state = SMTP_DATA;
510 }
511 } 614 }
512 615
513 case SMTP_RCPT_TO: 616 case SMTP_RCPT_TO:
514 if (smtp->rcpt_to) 617 status = smtp_write (smtp);
515 { 618 CHECK_EAGAIN (smtp, status);
516 status = smtp_write (smtp); 619 smtp->state = SMTP_RCPT_TO_ACK;
517 CHECK_EAGAIN (smtp, status);
518 smtp->state = SMTP_RCPT_TO_ACK;
519 }
520 620
521 case SMTP_RCPT_TO_ACK: 621 case SMTP_RCPT_TO_ACK:
522 if (smtp->rcpt_to) 622 status = smtp_read_ack (smtp);
623 CHECK_EAGAIN (smtp, status);
624 if (smtp->buffer[0] != '2')
523 { 625 {
524 status = smtp_read_ack (smtp); 626 stream_close (mailer->stream);
525 CHECK_EAGAIN (smtp, status); 627 CLEAR_STATE (smtp);
526 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); 628 return MU_ERR_SMTP_RCPT_FAILED;
527 if (smtp->buffer[0] != '2')
528 {
529 stream_close (mailer->stream);
530 CLEAR_STATE (smtp);
531 return EACCES;
532 }
533 goto RCPT_TO;
534 } 629 }
535 /* We are done with the rcpt. */ 630 /* Redo the receipt sequence for every To: and Cc: recipient. */
631 if (!smtp->bccing && smtp->rcpt_index <= smtp->rcpt_to_count)
632 goto ENV_RCPT;
633
634 /* We are done with the rcpt. */
536 status = smtp_writeline (smtp, "DATA\r\n"); 635 status = smtp_writeline (smtp, "DATA\r\n");
537 CHECK_ERROR (smtp, status); 636 CHECK_ERROR (smtp, status);
538 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer);
539 smtp->state = SMTP_DATA; 637 smtp->state = SMTP_DATA;
540 638
541 case SMTP_DATA: 639 case SMTP_DATA:
...@@ -546,7 +644,6 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to) ...@@ -546,7 +644,6 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to)
546 case SMTP_DATA_ACK: 644 case SMTP_DATA_ACK:
547 status = smtp_read_ack (smtp); 645 status = smtp_read_ack (smtp);
548 CHECK_EAGAIN (smtp, status); 646 CHECK_EAGAIN (smtp, status);
549 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer);
550 if (smtp->buffer[0] != '3') 647 if (smtp->buffer[0] != '3')
551 { 648 {
552 stream_close (mailer->stream); 649 stream_close (mailer->stream);
...@@ -565,12 +662,12 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to) ...@@ -565,12 +662,12 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to)
565 in the buffer and flush it. */ 662 in the buffer and flush it. */
566 status = smtp_write (smtp); 663 status = smtp_write (smtp);
567 CHECK_EAGAIN (smtp, status); 664 CHECK_EAGAIN (smtp, status);
568 message_get_stream (msg, &stream); 665 message_get_stream (smtp->msg, &stream);
569 while ((status = stream_readline (stream, data, sizeof (data) - 1, 666 while ((status = stream_readline (stream, data, sizeof (data) - 1,
570 smtp->offset, &n)) == 0 && n > 0) 667 smtp->offset, &n)) == 0 && n > 0)
571 { 668 {
572 if (data [n - 1] == '\n') 669 if (data[n - 1] == '\n')
573 data [n -1] = '\0'; 670 data[n - 1] = '\0';
574 if (data[0] == '.') 671 if (data[0] == '.')
575 { 672 {
576 status = smtp_writeline (smtp, ".%s\r\n", data); 673 status = smtp_writeline (smtp, ".%s\r\n", data);
...@@ -582,8 +679,7 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to) ...@@ -582,8 +679,7 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to)
582 CHECK_ERROR (smtp, status); 679 CHECK_ERROR (smtp, status);
583 } 680 }
584 smtp->offset += n; 681 smtp->offset += n;
585 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer); 682 status = smtp_write (smtp);
586 status = smtp_write (smtp);
587 CHECK_EAGAIN (smtp, status); 683 CHECK_EAGAIN (smtp, status);
588 } 684 }
589 smtp->offset = 0; 685 smtp->offset = 0;
...@@ -600,8 +696,6 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to) ...@@ -600,8 +696,6 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to)
600 case SMTP_SEND_ACK: 696 case SMTP_SEND_ACK:
601 status = smtp_read_ack (smtp); 697 status = smtp_read_ack (smtp);
602 CHECK_EAGAIN (smtp, status); 698 CHECK_EAGAIN (smtp, status);
603 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer);
604 observable_notify (mailer->observable, MU_EVT_MAILER_MESSAGE_SENT);
605 if (smtp->buffer[0] != '2') 699 if (smtp->buffer[0] != '2')
606 { 700 {
607 stream_close (mailer->stream); 701 stream_close (mailer->stream);
...@@ -609,6 +703,18 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to) ...@@ -609,6 +703,18 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to)
609 return EACCES; 703 return EACCES;
610 } 704 }
611 705
706 /* Decide whether we need to loop again, to deliver to Bcc:
707 recipients. */
708 if (!smtp->bccing)
709 {
710 smtp->bccing = 1;
711 smtp->rcpt_index = 1;
712 }
713 if (smtp->rcpt_index <= smtp->rcpt_bcc_count)
714 goto ENV_FROM;
715
716 observable_notify (mailer->observable, MU_EVT_MAILER_MESSAGE_SENT);
717
612 default: 718 default:
613 break; 719 break;
614 } 720 }
...@@ -617,125 +723,229 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to) ...@@ -617,125 +723,229 @@ smtp_send_message(mailer_t mailer, message_t msg, address_t from, address_t to)
617 } 723 }
618 724
619 static int 725 static int
620 get_from (message_t msg, char *localhost, address_t *pmail_from) 726 _smtp_set_from (smtp_t smtp, message_t msg, address_t from)
621 { 727 {
622 int status; 728 int status = 0;
623 size_t size = 0; 729 char *mail_from;
624 char *from;
625 header_t header = NULL; 730 header_t header = NULL;
626 731
627 message_get_header (msg, &header); 732 /* Get MAIL_FROM from FROM, the message, or the environment. */
628 status = header_get_value (header, MU_HEADER_FROM, NULL, 0, &size); 733 if (from)
629 /* If it's not in the header create one form the passwd. */
630 if (status != 0 || size == 0)
631 { 734 {
632 struct passwd *pwd = mu_getpwuid (getuid ()); 735 /* Use the specified address_t. */
633 /* Not in the passwd ???? We have a problem. */ 736 if ((status = mailer_check_from (from)) != 0)
634 if (pwd == 0 || pwd->pw_name == NULL)
635 {
636 size = 10 + strlen (localhost) + 1;
637 from = calloc (size, sizeof (char));
638 if (from == NULL)
639 return ENOMEM;
640 snprintf (from, size, "%d@%s", getuid(), localhost);
641 }
642 else
643 { 737 {
644 from = calloc (strlen (pwd->pw_name) + 1 738 MAILER_DEBUG0 (smtp->mailer, MU_DEBUG_ERROR,
645 + strlen (localhost) + 1, sizeof (char)); 739 "mailer_send_message(): explicit from not valid\n");
646 if (from == NULL) 740 return status;
647 return ENOMEM;
648 sprintf(from, "%s@%s", pwd->pw_name, localhost);
649 } 741 }
742
743 if ((status = address_aget_email (from, 1, &mail_from)) != 0)
744 return status;
650 } 745 }
651 else 746 else
652 { 747 {
653 from = calloc (size + 1, sizeof (char)); 748 char *from_hdr = NULL;
654 if (from == NULL) 749
655 return ENOMEM; 750 if ((status = message_get_header (msg, &header)) != 0)
656 header_get_value (header, MU_HEADER_FROM, from, size + 1, NULL); 751 return status;
657 } 752
658 /* Check if a Fully Qualified Name, some smtp servers 753 status = header_aget_value (header, MU_HEADER_FROM, &from_hdr);
659 notably sendmail insists on it, for good reasons. */ 754
660 if (strchr (from, '@') == NULL) 755 switch (status)
661 {
662 char *tmp;
663 tmp = malloc (strlen (from) + 1 +strlen (localhost) + 1);
664 if (tmp == NULL)
665 { 756 {
666 free (from); 757 default:
667 return ENOMEM; 758 return status;
759
760 /* Use the From: header. */
761 case 0:
762 {
763 address_t fromaddr = NULL;
764
765 MAILER_DEBUG1 (smtp->mailer, MU_DEBUG_TRACE,
766 "mailer_send_message(): using From: %s\n",
767 from_hdr);
768
769 if ((status = address_create (&fromaddr, from_hdr)) != 0)
770 {
771 free (from_hdr);
772 return status;
773 }
774 if ((status = mailer_check_from (fromaddr)) != 0)
775 {
776 free (from_hdr);
777 address_destroy (&fromaddr);
778 MAILER_DEBUG1 (smtp->mailer, MU_DEBUG_ERROR,
779 "mailer_send_message(): from field %s not valid\n",
780 from_hdr);
781 return status;
782 }
783 if ((status = address_aget_email (fromaddr, 1, &mail_from)) != 0)
784 {
785 free (from_hdr);
786 address_destroy (&fromaddr);
787 return status;
788 }
789 free (from_hdr);
790 address_destroy (&fromaddr);
791 }
792 break;
793
794 case ENOENT:
795 /* Use the environment. */
796 mail_from = mu_get_user_email (NULL);
797
798 if (mail_from)
799 {
800 MAILER_DEBUG1 (smtp->mailer, MU_DEBUG_TRACE,
801 "mailer_send_message(): using user's address: %s\n",
802 mail_from);
803 }
804 else
805 {
806 MAILER_DEBUG0 (smtp->mailer, MU_DEBUG_TRACE,
807 "mailer_send_message(): no user's address, failing\n");
808 }
809
810 if (!mail_from)
811 return errno;
812
813 status = 0;
814
815 /* FIXME: should we add the From: header? */
816
817 break;
818
668 } 819 }
669 sprintf (tmp, "%s@%s", from, localhost);
670 free (from);
671 from = tmp;
672 } 820 }
673 status = address_create (pmail_from, from); 821
674 free (from); 822 assert (mail_from);
823
824 smtp->mail_from = mail_from;
825
675 return status; 826 return status;
676 } 827 }
677 828
678 static int 829 static int
679 get_rcpt (message_t msg, address_t *prcpt_to) 830 _smtp_set_rcpt (smtp_t smtp, message_t msg, address_t to)
680 { 831 {
681 char *rcpt; 832 int status = 0;
682 int status;
683 size_t size = 0;
684 header_t header = NULL; 833 header_t header = NULL;
834 char *toaddrv[3] = { NULL, NULL };
835 char *bccaddr = NULL;
836 address_t rcpt_to = NULL;
837 address_t rcpt_bcc = NULL;
685 838
686 message_get_header (msg, &header); 839 /* Get RCPT_TO from TO, or the message. */
687 status = header_get_value (header, MU_HEADER_TO, NULL, 0, &size);
688 if (status == 0 && size != 0)
689 {
690 char *tmp;
691 size_t len;
692 rcpt = calloc (size + 1, sizeof (char));
693 if (rcpt == NULL)
694 return ENOMEM;
695 header_get_value (header, MU_HEADER_TO, rcpt, size + 1, NULL);
696 840
697 size = 0; 841 if (to)
698 status = header_get_value (header, MU_HEADER_CC, NULL, 0, &size); 842 {
699 if (status == 0 && size != 0) 843 /* Use the specified address_t. */
844 if ((status = mailer_check_to (to)) != 0)
700 { 845 {
701 len = strlen (rcpt); 846 MAILER_DEBUG0 (smtp->mailer, MU_DEBUG_ERROR,
702 tmp = realloc (rcpt, (len + 1 + size + 1) * sizeof (char)); 847 "mailer_send_message(): explicit to not valid\n");
703 if (tmp == NULL) 848 return status;
704 {
705 free (rcpt);
706 return ENOMEM;
707 }
708 else
709 rcpt = tmp;
710 rcpt[len] = ',';
711 header_get_value (header, MU_HEADER_CC, rcpt + len + 1,
712 size + 1, NULL);
713
714 size = 0;
715 status = header_get_value (header, MU_HEADER_BCC, NULL, 0, &size);
716 if (status == 0 && size != 0)
717 {
718 len = strlen (rcpt);
719 tmp = realloc (rcpt, (len + 1 + size + 1) * sizeof (char));
720 if (tmp == NULL)
721 {
722 free (rcpt);
723 return ENOMEM;
724 }
725 else
726 rcpt = tmp;
727 rcpt[len] = ',';
728 header_get_value (header, MU_HEADER_BCC, rcpt + len + 1,
729 size + 1, NULL);
730 }
731 } 849 }
732 status = address_create (prcpt_to, rcpt); 850 smtp->rcpt_to = to;
733 free (rcpt); 851
734 return status; 852 return status;
735 } 853 }
736 return EINVAL;
737 }
738 854
855 if ((status = message_get_header (msg, &header)))
856 return status;
857
858 status = header_aget_value (header, MU_HEADER_TO, toaddrv + 0);
859
860 if (status && status != ENOENT)
861 goto end;
862
863 status = header_aget_value (header, MU_HEADER_CC, toaddrv + 1);
864
865 if (status && status != ENOENT)
866 goto end;
867
868 status = header_aget_value (header, MU_HEADER_BCC, &bccaddr);
869
870 if (status && status != ENOENT)
871 goto end;
872
873 status = 0;
874
875 {
876 const char **av = (const char **) toaddrv;
877 int tostatus = address_createv (&rcpt_to, av, 2);
878
879 /* Any error other than EMPTY_ADDRESS is fatal */
880 if (tostatus)
881 {
882 if (tostatus == MU_ERR_EMPTY_ADDRESS)
883 tostatus = MU_ERR_MAILER_NO_RCPT_TO;
884 else
885 goto end;
886 }
887
888 if (!bccaddr)
889 status = MU_ERR_EMPTY_ADDRESS;
890 else
891 {
892 status = address_create (&rcpt_bcc, bccaddr);
893
894 if (status)
895 {
896 if (status == MU_ERR_EMPTY_ADDRESS)
897 status = MU_ERR_MAILER_NO_RCPT_TO;
898 else
899 goto end;
900 }
901 }
902
903 /* If both to and bcc are empty, it is fatal */
904 if (status == MU_ERR_EMPTY_ADDRESS && tostatus == status)
905 goto end;
906
907 /* otherwise, at least rcpt_to or rcpt_bcc is defined */
908 status = 0;
909 }
910
911 /* If to or bcc is present, the must be OK. */
912 if (rcpt_to && (status = mailer_check_to (rcpt_to)))
913 goto end;
914
915 if (rcpt_bcc && (status = mailer_check_to (rcpt_bcc)))
916 goto end;
917
918 end:
919
920 if (toaddrv[0])
921 free (toaddrv[0]);
922
923 if (toaddrv[1])
924 free (toaddrv[1]);
925
926 if (bccaddr)
927 free (bccaddr);
928
929 if (status)
930 {
931 address_destroy (&rcpt_to);
932 address_destroy (&rcpt_bcc);
933 }
934 else
935 {
936 smtp->rcpt_to = rcpt_to;
937
938 if (smtp->rcpt_to)
939 address_get_count (smtp->rcpt_to, &smtp->rcpt_to_count);
940
941 smtp->rcpt_bcc = rcpt_bcc;
942
943 if (smtp->rcpt_bcc)
944 address_get_count (smtp->rcpt_bcc, &smtp->rcpt_bcc_count);
945 }
946
947 return status;
948 }
739 /* C99 says that a conforming implementations of snprintf () 949 /* C99 says that a conforming implementations of snprintf ()
740 should return the number of char that would have been call 950 should return the number of char that would have been call
741 but many GNU/Linux && BSD implementations return -1 on error. 951 but many GNU/Linux && BSD implementations return -1 on error.
...@@ -748,25 +958,36 @@ smtp_writeline (smtp_t smtp, const char *format, ...) ...@@ -748,25 +958,36 @@ smtp_writeline (smtp_t smtp, const char *format, ...)
748 va_list ap; 958 va_list ap;
749 int done = 1; 959 int done = 1;
750 960
751 va_start(ap, format); 961 va_start (ap, format);
752 do 962 do
753 { 963 {
754 len = vsnprintf (smtp->buffer, smtp->buflen - 1, format, ap); 964 len = vsnprintf (smtp->buffer, smtp->buflen - 1, format, ap);
755 if (len < 0 || (len >= (int)smtp->buflen) 965 if (len < 0 || (len >= (int) smtp->buflen)
756 || !memchr (smtp->buffer, '\0', len + 1)) 966 || !memchr (smtp->buffer, '\0', len + 1))
757 { 967 {
758 smtp->buflen *= 2; 968 char *buffer = NULL;
759 smtp->buffer = realloc (smtp->buffer, smtp->buflen); 969 size_t buflen = smtp->buflen * 2;
760 if (smtp->buffer == NULL) 970 buffer = realloc (smtp->buffer, buflen);
761 return ENOMEM; 971 if (smtp->buffer == NULL)
972 return ENOMEM;
973 smtp->buffer = buffer;
974 smtp->buflen = buflen;
762 done = 0; 975 done = 0;
763 } 976 }
764 else 977 else
765 done = 1; 978 done = 1;
766 } 979 }
767 while (!done); 980 while (!done);
768 va_end(ap); 981
982 va_end (ap);
983
769 smtp->ptr = smtp->buffer + len; 984 smtp->ptr = smtp->buffer + len;
985
986 while (len > 0 && isspace (smtp->buffer[len-1]))
987 len--;
988
989 MAILER_DEBUG2 (smtp->mailer, MU_DEBUG_PROT, "> %.*s\n", len, smtp->buffer);
990
770 return 0; 991 return 0;
771 } 992 }
772 993
...@@ -781,10 +1002,10 @@ smtp_write (smtp_t smtp) ...@@ -781,10 +1002,10 @@ smtp_write (smtp_t smtp)
781 status = stream_write (smtp->mailer->stream, smtp->buffer, len, 1002 status = stream_write (smtp->mailer->stream, smtp->buffer, len,
782 0, &len); 1003 0, &len);
783 if (status == 0) 1004 if (status == 0)
784 { 1005 {
785 memmove (smtp->buffer, smtp->buffer + len, len); 1006 memmove (smtp->buffer, smtp->buffer + len, len);
786 smtp->ptr -= len; 1007 smtp->ptr -= len;
787 } 1008 }
788 } 1009 }
789 else 1010 else
790 { 1011 {
...@@ -804,8 +1025,7 @@ smtp_read_ack (smtp_t smtp) ...@@ -804,8 +1025,7 @@ smtp_read_ack (smtp_t smtp)
804 { 1025 {
805 multi = 0; 1026 multi = 0;
806 status = smtp_readline (smtp); 1027 status = smtp_readline (smtp);
807 if ((smtp->ptr - smtp->buffer) > 4 1028 if ((smtp->ptr - smtp->buffer) > 4 && smtp->buffer[3] == '-')
808 && smtp->buffer[3] == '-')
809 multi = 1; 1029 multi = 1;
810 if (status == 0) 1030 if (status == 0)
811 smtp->ptr = smtp->buffer; 1031 smtp->ptr = smtp->buffer;
...@@ -832,7 +1052,7 @@ smtp_readline (smtp_t smtp) ...@@ -832,7 +1052,7 @@ smtp_readline (smtp_t smtp)
832 status = stream_readline (smtp->mailer->stream, smtp->buffer + total, 1052 status = stream_readline (smtp->mailer->stream, smtp->buffer + total,
833 smtp->buflen - total, smtp->s_offset, &n); 1053 smtp->buflen - total, smtp->s_offset, &n);
834 if (status != 0) 1054 if (status != 0)
835 return status; 1055 return status;
836 1056
837 /* Server went away, consider this like an error. */ 1057 /* Server went away, consider this like an error. */
838 if (n == 0) 1058 if (n == 0)
...@@ -841,17 +1061,17 @@ smtp_readline (smtp_t smtp) ...@@ -841,17 +1061,17 @@ smtp_readline (smtp_t smtp)
841 total += n; 1061 total += n;
842 smtp->s_offset += n; 1062 smtp->s_offset += n;
843 smtp->nl = memchr (smtp->buffer, '\n', total); 1063 smtp->nl = memchr (smtp->buffer, '\n', total);
844 if (smtp->nl == NULL) /* Do we have a full line. */ 1064 if (smtp->nl == NULL) /* Do we have a full line. */
845 { 1065 {
846 /* Allocate a bigger buffer ? */ 1066 /* Allocate a bigger buffer ? */
847 if (total >= smtp->buflen -1) 1067 if (total >= smtp->buflen - 1)
848 { 1068 {
849 smtp->buflen *= 2; 1069 smtp->buflen *= 2;
850 smtp->buffer = realloc (smtp->buffer, smtp->buflen + 1); 1070 smtp->buffer = realloc (smtp->buffer, smtp->buflen + 1);
851 if (smtp->buffer == NULL) 1071 if (smtp->buffer == NULL)
852 return ENOMEM; 1072 return ENOMEM;
853 } 1073 }
854 } 1074 }
855 smtp->ptr = smtp->buffer + total; 1075 smtp->ptr = smtp->buffer + total;
856 } 1076 }
857 while (smtp->nl == NULL); 1077 while (smtp->nl == NULL);
...@@ -863,5 +1083,9 @@ smtp_readline (smtp_t smtp) ...@@ -863,5 +1083,9 @@ smtp_readline (smtp_t smtp)
863 *(smtp->nl) = '\0'; 1083 *(smtp->nl) = '\0';
864 smtp->ptr = smtp->nl; 1084 smtp->ptr = smtp->nl;
865 } 1085 }
1086
1087 MAILER_DEBUG1 (smtp->mailer, MU_DEBUG_PROT, "< %s", smtp->buffer);
1088
866 return 0; 1089 return 0;
867 } 1090 }
1091
......