summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/smtp
authorzautrix <zautrix>2005-03-18 20:17:03 (UTC)
committer zautrix <zautrix>2005-03-18 20:17:03 (UTC)
commit9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf (patch) (unidiff)
tree2528e6cc740225ca0f47d5ac8ff70f7d3bb10621 /libetpan/src/low-level/smtp
parent9319998f20f03dcc217fbb39656755dc65226276 (diff)
downloadkdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.zip
kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.tar.gz
kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.tar.bz2
Initial revision
Diffstat (limited to 'libetpan/src/low-level/smtp') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/smtp/TODO1
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp.c984
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp.h94
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_helper.c228
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_helper.h74
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_socket.c99
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_socket.h56
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_ssl.c74
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_ssl.h55
-rw-r--r--libetpan/src/low-level/smtp/mailsmtp_types.h126
10 files changed, 1791 insertions, 0 deletions
diff --git a/libetpan/src/low-level/smtp/TODO b/libetpan/src/low-level/smtp/TODO
new file mode 100644
index 0000000..96f44c6
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/TODO
@@ -0,0 +1 @@
- STARTTLS
diff --git a/libetpan/src/low-level/smtp/mailsmtp.c b/libetpan/src/low-level/smtp/mailsmtp.c
new file mode 100644
index 0000000..85659e9
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp.c
@@ -0,0 +1,984 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa,
5 * All rights reserved.
6 *
7 * SMTP AUTH support by Juergen Graf
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the libEtPan! project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34/*
35 * $Id$
36 */
37
38#include "mailsmtp.h"
39#include "connect.h"
40#include "md5.h"
41#include "base64.h"
42#include "mail.h"
43
44#include <netinet/in.h>
45#include <string.h>
46#include <stdlib.h>
47#include <unistd.h>
48#include <stdio.h>
49
50
51/*
52 RFC 2821 : SMTP
53 RFC 1891 : SMTP Service Extension for Delivery Status Notifications
54
55 RFC 1428 : Transition of Internet Mail from Just-Send-8 to 8bit-SMTP/MIME
56 RFC 1652 : SMTP Service Extension for 8bit-MIMEtransport
57 RFC 1845 : SMTP Service Extension for Checkpoint/Restart
58 RFC 1846 : SMTP 521 Reply Code
59 RFC 1870 : SMTP Service Extension for Message Size Declaration
60 RFC 1985 : SMTP Service Extension for Remote Message Queue Starting
61 RFC 2034 : SMTP Service Extension for Returning Enhanced Error Codes
62 RFC 2442 : The Batch SMTP Media Type
63 RFC 2487 : SMTP Service Extension for Secure SMTP over TLS
64 RFC 2505 : Anti-Spam Recommendations for SMTP MTAs
65 RFC 2554 : SMTP Service Extension for Authentication
66 RFC 2645 : ON-DEMAND MAIL RELAY (ODMR) SMTP with Dynamic IP Addresses
67 RFC 2852 : Deliver By SMTP Service Extension
68 RFC 2920 : SMTP Service Extension for Command Pipelining
69 RFC 3030 : SMTP Service Extensions for Transmission of Large and Binary MIME
70 Messages
71*/
72
73#define SMTP_STATUS_CONTINUE 0x1000
74
75mailsmtp * mailsmtp_new(size_t progr_rate,
76 progress_function * progr_fun)
77{
78 mailsmtp * session;
79
80 session = malloc(sizeof(* session));
81 if (session == NULL)
82 goto err;
83
84 session->stream = NULL;
85
86 session->progr_rate = progr_rate;
87 session->progr_fun = progr_fun;
88
89 session->response = NULL;
90
91 session->line_buffer = mmap_string_new("");
92 if (session->line_buffer == NULL)
93 goto free_session;
94
95 session->response_buffer = mmap_string_new("");
96 if (session->response_buffer == NULL)
97 goto free_line_buffer;
98
99 session->esmtp = 0;
100 session->auth = MAILSMTP_AUTH_NOT_CHECKED;
101
102 return session;
103
104 free_line_buffer:
105 mmap_string_free(session->line_buffer);
106 free_session:
107 free(session);
108 err:
109 return NULL;
110}
111
112void mailsmtp_free(mailsmtp * session)
113{
114 if (session->stream)
115 mailsmtp_quit(session);
116
117 mmap_string_free(session->line_buffer);
118 mmap_string_free(session->response_buffer);
119 free(session);
120}
121
122static int send_command(mailsmtp * f, char * command);
123
124static int read_response(mailsmtp * session);
125
126/* smtp operations */
127
128int mailsmtp_connect(mailsmtp * session, mailstream * s)
129{
130 int code;
131
132 session->stream = s;
133
134 code = read_response(session);
135
136 switch (code) {
137 case 220:
138 return MAILSMTP_NO_ERROR;
139
140 case 554:
141 session->stream = NULL;
142 mailstream_close(s);
143 return MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE;
144
145 default:
146 session->stream = NULL;
147 mailstream_close(s);
148 return MAILSMTP_ERROR_UNEXPECTED_CODE;
149 }
150}
151
152
153#define SMTP_STRING_SIZE 513
154
155int mailsmtp_quit(mailsmtp * session)
156{
157 char command[SMTP_STRING_SIZE];
158 int r;
159
160 snprintf(command, SMTP_STRING_SIZE, "QUIT\r\n");
161 r = send_command(session, command);
162 if (r == -1)
163 return MAILSMTP_ERROR_STREAM;
164 r = read_response(session);
165 if (r == 0)
166 return MAILSMTP_ERROR_STREAM;
167 mailstream_close(session->stream);
168 session->stream = NULL;
169
170 return MAILSMTP_NO_ERROR;
171}
172
173
174
175#define HOSTNAME_SIZE 256
176
177int mailsmtp_helo(mailsmtp * session)
178{
179 int r;
180 char hostname[HOSTNAME_SIZE];
181 char command[SMTP_STRING_SIZE];
182
183 r = gethostname(hostname, HOSTNAME_SIZE);
184 if (r < 0)
185 return MAILSMTP_ERROR_HOSTNAME;
186
187 snprintf(command, SMTP_STRING_SIZE, "HELO %s\r\n", hostname);
188 r = send_command(session, command);
189 if (r == -1)
190 return MAILSMTP_ERROR_STREAM;
191 r = read_response(session);
192
193 switch (r) {
194 case 250:
195 session->esmtp = 0;
196 session->auth = MAILSMTP_AUTH_NOT_CHECKED;
197 return MAILSMTP_NO_ERROR;
198
199 case 504:
200 return MAILSMTP_ERROR_NOT_IMPLEMENTED;
201
202 case 550:
203 return MAILSMTP_ERROR_ACTION_NOT_TAKEN;
204
205 case 0:
206 return MAILSMTP_ERROR_STREAM;
207
208 default:
209 return MAILSMTP_ERROR_UNEXPECTED_CODE;
210 }
211}
212
213int mailsmtp_mail(mailsmtp * session, const char * from)
214{
215 int r;
216 char command[SMTP_STRING_SIZE];
217
218 snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s>\r\n", from);
219 r = send_command(session, command);
220 if (r == -1)
221 return MAILSMTP_ERROR_STREAM;
222 r = read_response(session);
223
224 switch (r) {
225 case 250:
226 return MAILSMTP_NO_ERROR;
227
228 case 552:
229 return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION;
230
231 case 451:
232 return MAILSMTP_ERROR_IN_PROCESSING;
233
234 case 452:
235 return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE;
236
237 case 550:
238 return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE;
239
240 case 553:
241 return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED;
242
243 case 503:
244 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
245
246 case 0:
247 return MAILSMTP_ERROR_STREAM;
248
249 default:
250 return MAILSMTP_ERROR_UNEXPECTED_CODE;
251 }
252}
253
254int mailsmtp_rcpt(mailsmtp * session, const char * to)
255{
256 return mailesmtp_rcpt(session, to, 0, NULL);
257}
258
259int mailsmtp_data(mailsmtp * session)
260{
261 int r;
262 char command[SMTP_STRING_SIZE];
263
264 snprintf(command, SMTP_STRING_SIZE, "DATA\r\n");
265 r = send_command(session, command);
266 if (r == -1)
267 return MAILSMTP_ERROR_STREAM;
268 r = read_response(session);
269
270 switch (r) {
271 case 354:
272 return MAILSMTP_NO_ERROR;
273
274 case 451:
275 return MAILSMTP_ERROR_IN_PROCESSING;
276
277 case 554:
278 return MAILSMTP_ERROR_TRANSACTION_FAILED;
279
280 case 503:
281 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
282
283 default:
284 return MAILSMTP_ERROR_UNEXPECTED_CODE;
285 }
286}
287
288static int send_data(mailsmtp * session, const char * message, size_t size);
289
290int mailsmtp_data_message(mailsmtp * session,
291 const char * message,
292 size_t size)
293{
294 int r;
295
296 r = send_data(session, message, size);
297 if (r == -1)
298 return MAILSMTP_ERROR_STREAM;
299
300 r = read_response(session);
301
302 switch(r) {
303 case 250:
304 return MAILSMTP_NO_ERROR;
305
306 case 552:
307 return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION;
308
309 case 554:
310 return MAILSMTP_ERROR_TRANSACTION_FAILED;
311
312 case 451:
313 return MAILSMTP_ERROR_IN_PROCESSING;
314
315 case 452:
316 return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE;
317
318 case 0:
319 return MAILSMTP_ERROR_STREAM;
320
321 default:
322 return MAILSMTP_ERROR_UNEXPECTED_CODE;
323 }
324}
325
326/* esmtp operations */
327
328
329/**
330 * called during mailesmtp_ehlo
331 * checks EHLO answer for server extensions and sets flags
332 * in session->esmtp
333 * checks AUTH methods in session->response and sets flags
334 * in session->auth
335 */
336#define isdelim(x) ((x) == ' ' || (x) == '\r' || (x) == '\n' || (x) == '\0')
337
338int mailesmtp_parse_ehlo(mailsmtp * session)
339{
340 char * response;
341
342 /* restore data */
343 session->esmtp = MAILSMTP_ESMTP;
344 session->auth = MAILSMTP_AUTH_CHECKED;
345
346 response = session->response;
347
348 /* ESMTP supported extensions :
349 DSN
350 EXPN
351 8BITMIME
352 SIZE [<n>]
353 ETRN
354 STARTTLS
355 AUTH <mechanisms...>
356 */
357 while (response != NULL) {
358 if (!strncasecmp(response, "EXPN", 4) && isdelim(response[4]))
359 session->esmtp |= MAILSMTP_ESMTP_EXPN;
360 else if (!strncasecmp(response, "ETRN", 4) && isdelim(response[4]))
361 session->esmtp |= MAILSMTP_ESMTP_ETRN;
362 else if (!strncasecmp(response, "DSN", 3) && isdelim(response[3]))
363 session->esmtp |= MAILSMTP_ESMTP_DSN;
364 else if (!strncasecmp(response, "8BITMIME", 8) && isdelim(response[8]))
365 session->esmtp |= MAILSMTP_ESMTP_8BITMIME;
366 else if (!strncasecmp(response, "STARTTLS", 8) && isdelim(response[8]))
367 session->esmtp |= MAILSMTP_ESMTP_STARTTLS;
368 else if (!strncasecmp(response, "SIZE", 4) && isdelim(response[4])) {
369 session->esmtp |= MAILSMTP_ESMTP_SIZE;
370 /* TODO: grab optionnal max size */
371 } else if (!strncasecmp(response, "AUTH ", 5)) {
372 response += 5; /* remove "AUTH " */
373 while (response[0] != '\n' && response[0] != '\0') {
374 while (response[0] == ' ') response++;
375 if (strncasecmp(response, "LOGIN", 5) == 0) {
376 session->auth |= MAILSMTP_AUTH_LOGIN;
377 response += 5;
378 } else if (strncasecmp(response, "CRAM-MD5", 8) == 0) {
379 session->auth |= MAILSMTP_AUTH_CRAM_MD5;
380 response += 8;
381 } else if (strncasecmp(response, "PLAIN", 5) == 0) {
382 session->auth |= MAILSMTP_AUTH_PLAIN;
383 response += 5;
384 } else {
385 /* unknown auth method - jump to next word or eol */
386 while (!isdelim(response[0]) || response[0] == '\r')
387 response++;
388 }
389 }
390 }
391 response = strpbrk(response, "\n");
392 if (response != NULL)
393 response++;
394 }
395
396 return MAILSMTP_NO_ERROR;
397}
398
399
400int mailesmtp_ehlo(mailsmtp * session)
401{
402 int r;
403 char hostname[HOSTNAME_SIZE];
404 char command[SMTP_STRING_SIZE];
405
406 r = gethostname(hostname, HOSTNAME_SIZE);
407 if (r != 0)
408 return MAILSMTP_ERROR_HOSTNAME;
409
410 snprintf(command, SMTP_STRING_SIZE, "EHLO %s\r\n", hostname);
411 r = send_command(session, command);
412 if (r == -1)
413 return MAILSMTP_ERROR_STREAM;
414 r = read_response(session);
415
416 switch (r) {
417 case 250:
418 return mailesmtp_parse_ehlo(session);
419
420 case 504:
421 return MAILSMTP_ERROR_NOT_IMPLEMENTED;
422
423 case 550:
424 return MAILSMTP_ERROR_ACTION_NOT_TAKEN;
425
426 case 0:
427 return MAILSMTP_ERROR_STREAM;
428
429 default:
430 return MAILSMTP_ERROR_UNEXPECTED_CODE;
431 }
432}
433
434/*
435 if return_full is TRUE, the entire message is returned on error
436 envid can be NULL
437*/
438
439
440int mailesmtp_mail(mailsmtp * session,
441 const char * from,
442 int return_full,
443 const char * envid)
444{
445 int r;
446 char command[SMTP_STRING_SIZE];
447 char *body = "";
448
449#if notyet
450 /* TODO: figure out a way for the user to explicity enable this or not */
451 if (session->esmtp & MAILSMTP_ESMTP_8BITMIME)
452 body = " BODY=8BITMIME";
453#endif
454
455 if (session->esmtp & MAILSMTP_ESMTP_DSN) {
456 if (envid)
457 snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s> RET=%s ENVID=%s%s\r\n",
458 from, return_full ? "FULL" : "HDRS", envid, body);
459 else
460 snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s> RET=%s%s\r\n",
461 from, return_full ? "FULL" : "HDRS", body);
462 } else
463 snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s>%s\r\n",
464 from, body);
465
466 r = send_command(session, command);
467 if (r == -1)
468 return MAILSMTP_ERROR_STREAM;
469 r = read_response(session);
470
471 switch (r) {
472 case 250:
473 return MAILSMTP_NO_ERROR;
474
475 case 552:
476 return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION;
477
478 case 451:
479 return MAILSMTP_ERROR_IN_PROCESSING;
480
481 case 452:
482 return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE;
483
484 case 550:
485 return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE;
486
487 case 553:
488 return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED;
489
490 case 503:
491 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
492
493 case 0:
494 return MAILSMTP_ERROR_STREAM;
495
496 default:
497 return MAILSMTP_ERROR_UNEXPECTED_CODE;
498 }
499}
500
501int mailesmtp_rcpt(mailsmtp * session,
502 const char * to,
503 int notify,
504 const char * orcpt)
505{
506 int r;
507 char command[SMTP_STRING_SIZE];
508 char notify_str[30] = "";
509 char notify_info_str[30] = "";
510
511 if (notify != 0 && session->esmtp & MAILSMTP_ESMTP_DSN) {
512 if (notify & MAILSMTP_DSN_NOTIFY_SUCCESS)
513 strcat(notify_info_str, ",SUCCESS");
514 if (notify & MAILSMTP_DSN_NOTIFY_FAILURE)
515 strcat(notify_info_str, ",FAILURE");
516 if (notify & MAILSMTP_DSN_NOTIFY_DELAY)
517 strcat(notify_info_str, ",DELAY");
518
519 if (notify & MAILSMTP_DSN_NOTIFY_NEVER)
520 strcpy(notify_info_str, ",NEVER");
521
522 notify_info_str[0] = '=';
523
524 strcpy(notify_str, " NOTIFY");
525 strcat(notify_str, notify_info_str);
526 }
527
528 if (orcpt && session->esmtp & MAILSMTP_ESMTP_DSN)
529 snprintf(command, SMTP_STRING_SIZE, "RCPT TO:<%s>%s ORCPT=%s\r\n",
530 to, notify_str, orcpt);
531 else
532 snprintf(command, SMTP_STRING_SIZE, "RCPT TO:<%s>%s\r\n", to, notify_str);
533
534 r = send_command(session, command);
535 if (r == -1)
536 return MAILSMTP_ERROR_STREAM;
537 r = read_response(session);
538
539 switch (r) {
540 case 250:
541 return MAILSMTP_NO_ERROR;
542
543 case 251: /* not local user, will be forwarded */
544 return MAILSMTP_NO_ERROR;
545
546 case 550:
547 case 450:
548 return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE;
549
550 case 551:
551 return MAILSMTP_ERROR_USER_NOT_LOCAL;
552
553 case 552:
554 return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION;
555
556 case 553:
557 return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED;
558
559 case 451:
560 return MAILSMTP_ERROR_IN_PROCESSING;
561
562 case 452:
563 return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE;
564
565 case 503:
566 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
567
568 case 0:
569 return MAILSMTP_ERROR_STREAM;
570
571 default:
572 return MAILSMTP_ERROR_UNEXPECTED_CODE;
573 }
574}
575
576int auth_map_errors(int err)
577{
578 switch (err) {
579 case 235:
580 return MAILSMTP_NO_ERROR; /* AUTH successfull */
581 case 334:
582 return MAILSMTP_NO_ERROR; /* AUTH in progress */
583 case 432:
584 return MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED;
585 case 454:
586 return MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE;
587 case 504:
588 return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED;
589 case 530:
590 return MAILSMTP_ERROR_AUTH_REQUIRED;
591 case 534:
592 return MAILSMTP_ERROR_AUTH_TOO_WEAK;
593 case 538:
594 return MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED;
595 default:
596 /* opportunistic approach ;) */
597 return MAILSMTP_NO_ERROR;
598 }
599}
600
601static int mailsmtp_auth_login(mailsmtp * session,
602 const char * user, const char * pass)
603{
604 int err;
605 char command[SMTP_STRING_SIZE];
606 char * user64, * pass64;
607
608 user64 = NULL;
609 pass64 = NULL;
610
611 user64 = encode_base64(user, strlen(user));
612 if (user64 == NULL) {
613 err = MAILSMTP_ERROR_MEMORY;
614 goto err_free;
615 }
616
617 pass64 = encode_base64(pass, strlen(pass));
618 if (pass64 == NULL) {
619 err = MAILSMTP_ERROR_MEMORY;
620 goto err_free;
621 }
622
623 snprintf(command, SMTP_STRING_SIZE, "%s\r\n", user64);
624 err = send_command(session, command);
625 if (err == -1) {
626 err = MAILSMTP_ERROR_STREAM;
627 goto err_free;
628 }
629 err = read_response(session);
630 err = auth_map_errors(err);
631 if (err != MAILSMTP_NO_ERROR)
632 goto err_free;
633
634 snprintf(command, SMTP_STRING_SIZE, "%s\r\n", pass64);
635 err = send_command(session, command);
636 if (err == -1) {
637 err = MAILSMTP_ERROR_STREAM;
638 goto err_free;
639 }
640 err = read_response(session);
641 err = auth_map_errors(err);
642
643 err_free:
644 free(user64);
645 free(pass64);
646
647 return err;
648}
649
650static int mailsmtp_auth_plain(mailsmtp * session,
651 const char * user, const char * pass)
652{
653 int err, len;
654 char command[SMTP_STRING_SIZE];
655 char * plain, * plain64;
656
657 len = strlen(user) + strlen(pass) + 3;
658 plain = (char *) malloc(len);
659 if (plain == NULL) {
660 err = MAILSMTP_ERROR_MEMORY;
661 goto err;
662 }
663
664 snprintf(plain, len, "%c%s%c%s", '\0', user, '\0', pass);
665 plain64 = encode_base64(plain, len - 1);
666
667 snprintf(command, SMTP_STRING_SIZE, "%s\r\n", plain64);
668 err = send_command(session, command);
669 if (err == -1) {
670 err = MAILSMTP_ERROR_STREAM;
671 goto err_free;
672 }
673
674 err = read_response(session);
675 err = auth_map_errors(err);
676
677err_free:
678 free(plain64);
679 free(plain);
680
681 err:
682 return err;
683}
684
685static char * convert_hex(unsigned char *in, int len)
686{
687 static char hex[] = "0123456789abcdef";
688 char * out;
689 int i;
690
691 out = (char *) malloc(len * 2 + 1);
692 if (out == NULL)
693 return NULL;
694
695 for (i = 0; i < len; i++) {
696 out[i * 2] = hex[in[i] >> 4];
697 out[i * 2 + 1] = hex[in[i] & 15];
698 }
699
700 out[i*2] = 0;
701
702 return out;
703}
704
705static char * hash_md5(const char * sec_key, const char * data, int len)
706{
707 char key[65], digest[24];
708 char * hash_hex;
709
710 int sec_len, i;
711
712 sec_len = strlen(sec_key);
713
714 if (sec_len < 64) {
715 memcpy(key, sec_key, sec_len);
716 for (i = sec_len; i < 64; i++) {
717 key[i] = 0;
718 }
719 } else {
720 memcpy(key, sec_key, 64);
721 }
722
723 hmac_md5(data, len, key, 64, digest);
724 hash_hex = convert_hex(digest, 16);
725
726 return hash_hex;
727}
728
729static int mailsmtp_auth_cram_md5(mailsmtp * session,
730 const char * user, const char * pass)
731{
732 int err;
733 char command[SMTP_STRING_SIZE];
734 char *response, *auth_hex, *auth;
735
736 response = decode_base64(session->response, strlen(session->response));
737 if (response == NULL) return MAILSMTP_ERROR_MEMORY;
738
739 auth_hex = hash_md5(pass, response, strlen(response));
740 if (auth_hex == NULL) {
741 err = MAILSMTP_ERROR_MEMORY;
742 goto err_free_response;
743 }
744
745 snprintf(command, SMTP_STRING_SIZE, "%s %s", user, auth_hex);
746
747 auth = encode_base64(command, strlen(command));
748 if (auth == NULL) {
749 err = MAILSMTP_ERROR_MEMORY;
750 goto err_free_auth_hex;
751 }
752
753 snprintf(command, SMTP_STRING_SIZE, "%s\r\n", auth);
754 err = send_command(session, command);
755 if (err == -1) {
756 err = MAILSMTP_ERROR_STREAM;
757 goto err_free;
758 }
759
760 err = read_response(session);
761 err = auth_map_errors(err);
762
763err_free:
764 free(auth);
765err_free_auth_hex:
766 free(auth_hex);
767err_free_response:
768 free(response);
769 return err;
770}
771
772int mailsmtp_auth_type(mailsmtp * session,
773 const char * user, const char * pass, int type)
774{
775 int err;
776 char command[SMTP_STRING_SIZE];
777
778 if (session->auth == MAILSMTP_AUTH_NOT_CHECKED)
779 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
780
781 if ( !(session->auth & type) ) return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED;
782
783 switch (type) {
784 case MAILSMTP_AUTH_LOGIN:
785 snprintf(command, SMTP_STRING_SIZE, "AUTH LOGIN\r\n");
786 break;
787 case MAILSMTP_AUTH_PLAIN:
788 snprintf(command, SMTP_STRING_SIZE, "AUTH PLAIN\r\n");
789 break;
790 case MAILSMTP_AUTH_CRAM_MD5:
791 snprintf(command, SMTP_STRING_SIZE, "AUTH CRAM-MD5\r\n");
792 break;
793 default:
794 return MAILSMTP_ERROR_NOT_IMPLEMENTED;
795 }
796
797 err = send_command(session, command);
798 if (err == -1) return MAILSMTP_ERROR_STREAM;
799
800 err = read_response(session);
801 err = auth_map_errors(err);
802 if (err != MAILSMTP_NO_ERROR) return err;
803
804 switch (type) {
805 case MAILSMTP_AUTH_LOGIN:
806 return mailsmtp_auth_login(session, user, pass);
807 case MAILSMTP_AUTH_PLAIN:
808 return mailsmtp_auth_plain(session, user, pass);
809 case MAILSMTP_AUTH_CRAM_MD5:
810 return mailsmtp_auth_cram_md5(session, user, pass);
811 default:
812 return MAILSMTP_ERROR_NOT_IMPLEMENTED;
813 }
814}
815
816
817int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass)
818{
819 if (session->auth == MAILSMTP_AUTH_NOT_CHECKED)
820 return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND;
821
822 if (session->auth & MAILSMTP_AUTH_CRAM_MD5) {
823 return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_CRAM_MD5);
824 } else if (session->auth & MAILSMTP_AUTH_PLAIN) {
825 return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_PLAIN);
826 } else if (session->auth & MAILSMTP_AUTH_LOGIN) {
827 return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_LOGIN);
828 } else {
829 return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED;
830 }
831}
832
833/* TODO: add mailesmtp_etrn, mailssmtp_expn */
834
835int mailesmtp_starttls(mailsmtp * session) {
836 int r;
837
838 if (!(session->esmtp & MAILSMTP_ESMTP_STARTTLS))
839 return MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED;
840
841 r = send_command(session, "STARTTLS\r\n");
842 if (r == -1)
843 return MAILSMTP_ERROR_STREAM;
844 r = read_response(session);
845
846 switch (r) {
847 case 220:
848 return MAILSMTP_NO_ERROR;
849
850 case 454:
851 return MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE;
852
853 default:
854 return MAILSMTP_ERROR_UNEXPECTED_CODE;
855 }
856}
857
858static int parse_response(mailsmtp * session,
859 char * response)
860{
861 char * message;
862 int code;
863 int cont = 0;
864
865 code = strtol(response, &message, 10);
866 if (* message == ' ')
867 mmap_string_append(session->response_buffer, message + 1);
868 else if (* message == '-') {
869 cont = SMTP_STATUS_CONTINUE;
870 mmap_string_append(session->response_buffer, message + 1);
871 }
872 else
873 mmap_string_append(session->response_buffer, message);
874
875 return code | cont;
876}
877
878static char * read_line(mailsmtp * session)
879{
880 return mailstream_read_line_remove_eol(session->stream,
881 session->line_buffer);
882}
883
884static int read_response(mailsmtp * session)
885{
886 char * line;
887 int code;
888
889 mmap_string_assign(session->response_buffer, "");
890
891 do {
892 line = read_line(session);
893
894 if (line != NULL) {
895 code = parse_response(session, line);
896 mmap_string_append_c(session->response_buffer, '\n');
897 }
898 else
899 code = 0;
900 }
901 while ((code & SMTP_STATUS_CONTINUE) != 0);
902
903 session->response = session->response_buffer->str;
904
905 return code;
906}
907
908
909
910
911
912static int send_command(mailsmtp * f, char * command)
913{
914 ssize_t r;
915
916 r = mailstream_write(f->stream, command, strlen(command));
917 if (r == -1)
918 return -1;
919
920 r = mailstream_flush(f->stream);
921 if (r == -1)
922 return -1;
923
924 return 0;
925}
926
927static int send_data(mailsmtp * session, const char * message, size_t size)
928{
929 if (mailstream_send_data(session->stream, message, size,
930 session->progr_rate, session->progr_fun) == -1)
931 return -1;
932
933 if (mailstream_flush(session->stream) == -1)
934 return -1;
935
936 return 0;
937}
938
939
940const char * mailsmtp_strerror(int errnum)
941{
942 switch (errnum) {
943 case MAILSMTP_NO_ERROR:
944 return "No error";
945 case MAILSMTP_ERROR_UNEXPECTED_CODE:
946 return "Unexpected error code";
947 case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE:
948 return "Service not available";
949 case MAILSMTP_ERROR_STREAM:
950 return "Stream error";
951 case MAILSMTP_ERROR_HOSTNAME:
952 return "gethostname() failed";
953 case MAILSMTP_ERROR_NOT_IMPLEMENTED:
954 return "Not implemented";
955 case MAILSMTP_ERROR_ACTION_NOT_TAKEN:
956 return "Error, action not taken";
957 case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION:
958 return "Data exceeds storage allocation";
959 case MAILSMTP_ERROR_IN_PROCESSING:
960 return "Error in processing";
961 case MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE:
962 return "Insufficient system storage";
963 case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE:
964 return "Mailbox unavailable";
965 case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED:
966 return "Mailbox name not allowed";
967 case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND:
968 return "Bad command sequence";
969 case MAILSMTP_ERROR_USER_NOT_LOCAL:
970 return "User not local";
971 case MAILSMTP_ERROR_TRANSACTION_FAILED:
972 return "Transaction failed";
973 case MAILSMTP_ERROR_MEMORY:
974 return "Memory error";
975 case MAILSMTP_ERROR_CONNECTION_REFUSED:
976 return "Connection refused";
977 case MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE:
978 return "TLS not available on server for temporary reason";
979 case MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED:
980 return "TLS not supported by server";
981 default:
982 return "Unknown error code";
983 }
984}
diff --git a/libetpan/src/low-level/smtp/mailsmtp.h b/libetpan/src/low-level/smtp/mailsmtp.h
new file mode 100644
index 0000000..72e1786
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp.h
@@ -0,0 +1,94 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_H
37
38#define MAILSMTP_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailsmtp_types.h>
45#include <libetpan/mailsmtp_helper.h>
46#include <libetpan/mailsmtp_socket.h>
47#include <libetpan/mailsmtp_ssl.h>
48
49
50mailsmtp * mailsmtp_new(size_t progr_rate,
51 progress_function * progr_fun);
52void mailsmtp_free(mailsmtp * session);
53
54int mailsmtp_connect(mailsmtp * session, mailstream * s);
55int mailsmtp_quit(mailsmtp * session);
56
57/**
58 * Tries AUTH with detected method - "better" method first:
59 * CRAM-MD5 -> PLAIN -> LOGIN
60 */
61int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass);
62
63/**
64 * tries to autenticate with the server using given auth-type
65 * returns MAILSMTP_NO_ERROR on success
66 */
67int mailsmtp_auth_type(mailsmtp * session,
68 const char * user, const char * pass, int type);
69
70int mailsmtp_helo(mailsmtp * session);
71int mailsmtp_mail(mailsmtp * session, const char * from);
72int mailsmtp_rcpt(mailsmtp * session, const char * to);
73int mailsmtp_data(mailsmtp * session);
74int mailsmtp_data_message(mailsmtp * session,
75 const char * message,
76 size_t size);
77int mailesmtp_ehlo(mailsmtp * session);
78int mailesmtp_mail(mailsmtp * session,
79 const char * from,
80 int return_full,
81 const char * envid);
82int mailesmtp_rcpt(mailsmtp * session,
83 const char * to,
84 int notify,
85 const char * orcpt);
86int mailesmtp_starttls(mailsmtp * session);
87
88const char * mailsmtp_strerror(int errnum);
89
90#ifdef __cplusplus
91}
92#endif
93
94#endif
diff --git a/libetpan/src/low-level/smtp/mailsmtp_helper.c b/libetpan/src/low-level/smtp/mailsmtp_helper.c
new file mode 100644
index 0000000..69b73cc
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_helper.c
@@ -0,0 +1,228 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailsmtp.h"
37#include <string.h>
38#include <stdlib.h>
39#include "mail.h"
40
41int mailsmtp_init(mailsmtp * session)
42{
43 int r;
44
45 r = mailesmtp_ehlo(session);
46
47 if (r == MAILSMTP_NO_ERROR)
48 return MAILSMTP_NO_ERROR;
49
50 r = mailsmtp_helo(session);
51 if (r == MAILSMTP_NO_ERROR)
52 return MAILSMTP_NO_ERROR;
53
54 return r;
55}
56
57
58
59int mailesmtp_send(mailsmtp * session,
60 const char * from,
61 int return_full,
62 const char * envid,
63 clist * addresses,
64 const char * message, size_t size)
65{
66 int r;
67 clistiter * l;
68
69 if (!session->esmtp)
70 return mailsmtp_send(session, from, addresses, message, size);
71
72 r = mailesmtp_mail(session, from, return_full, envid);
73 if (r != MAILSMTP_NO_ERROR)
74 return r;
75
76 for(l = clist_begin(addresses) ; l != NULL; l = clist_next(l)) {
77 struct esmtp_address * addr;
78
79 addr = clist_content(l);
80
81 r = mailesmtp_rcpt(session, addr->address, addr->notify, addr->orcpt);
82 if (r != MAILSMTP_NO_ERROR)
83 return r;
84 }
85
86 r = mailsmtp_data(session);
87 if (r != MAILSMTP_NO_ERROR)
88 return r;
89
90 r = mailsmtp_data_message(session, message, size);
91 if (r != MAILSMTP_NO_ERROR)
92 return r;
93
94 return MAILSMTP_NO_ERROR;
95}
96
97int mailsmtp_send(mailsmtp * session,
98 const char * from,
99 clist * addresses,
100 const char * message, size_t size)
101{
102 int r;
103 clistiter * l;
104
105 r = mailsmtp_mail(session, from);
106 if (r != MAILSMTP_NO_ERROR)
107 return r;
108
109 for(l = clist_begin(addresses) ; l != NULL; l = clist_next(l)) {
110 struct esmtp_address * addr;
111
112 addr = clist_content(l);
113
114 r = mailsmtp_rcpt(session, addr->address);
115 if (r != MAILSMTP_NO_ERROR)
116 return r;
117 }
118
119 r = mailsmtp_data(session);
120 if (r != MAILSMTP_NO_ERROR)
121 return r;
122
123 r = mailsmtp_data_message(session, message, size);
124 if (r != MAILSMTP_NO_ERROR)
125 return r;
126
127 return MAILSMTP_NO_ERROR;
128}
129
130
131
132
133
134
135
136
137
138
139
140
141
142/* esmtp addresses and smtp addresses */
143
144static struct esmtp_address * esmtp_address_new(char * addr,
145 int notify, char * orcpt)
146{
147 struct esmtp_address * esmtpa;
148
149 esmtpa = malloc(sizeof(* esmtpa));
150 if (esmtpa == NULL)
151 return NULL;
152
153 esmtpa->address = strdup(addr);
154 if (esmtpa->address == NULL) {
155 free(esmtpa);
156 return NULL;
157 }
158
159 if (orcpt != NULL) {
160 esmtpa->orcpt = strdup(orcpt);
161 if (esmtpa->orcpt == NULL) {
162 free(esmtpa->address);
163 free(esmtpa);
164 return NULL;
165 }
166 }
167 else
168 esmtpa->orcpt = NULL;
169
170 esmtpa->notify = notify;
171
172 return esmtpa;
173}
174
175static void esmtp_address_free(struct esmtp_address * addr)
176{
177 if (addr->orcpt)
178 free(addr->orcpt);
179 if (addr->address)
180 free(addr->address);
181
182 free(addr);
183}
184
185clist * esmtp_address_list_new()
186{
187 return clist_new();
188}
189
190void esmtp_address_list_free(clist * l)
191{
192 clist_foreach(l, (clist_func) esmtp_address_free, NULL);
193 clist_free(l);
194}
195
196int esmtp_address_list_add(clist * list, char * address,
197 int notify, char * orcpt)
198{
199 struct esmtp_address * esmtpa;
200 int r;
201
202 esmtpa = esmtp_address_new(address, notify, orcpt);
203 if (esmtpa == NULL)
204 return -1;
205
206 r = clist_append(list, esmtpa);
207 if (r < 0) {
208 esmtp_address_free(esmtpa);
209 return -1;
210 }
211
212 return 0;
213}
214
215clist * smtp_address_list_new()
216{
217 return esmtp_address_list_new();
218}
219
220int smtp_address_list_add(clist * list, char * address)
221{
222 return esmtp_address_list_add(list, address, 0, NULL);
223}
224
225void smtp_address_list_free(clist * l)
226{
227 esmtp_address_list_free(l);
228}
diff --git a/libetpan/src/low-level/smtp/mailsmtp_helper.h b/libetpan/src/low-level/smtp/mailsmtp_helper.h
new file mode 100644
index 0000000..2178d50
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_helper.h
@@ -0,0 +1,74 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_HELPER_H
37
38#define MAILSMTP_HELPER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailsmtp_types.h"
45#include "clist.h"
46
47int mailsmtp_init(mailsmtp * session);
48
49int mailesmtp_send(mailsmtp * session,
50 const char * from,
51 int return_full,
52 const char * envid,
53 clist * addresses,
54 const char * message, size_t size);
55
56int mailsmtp_send(mailsmtp * session,
57 const char * from,
58 clist * addresses,
59 const char * message, size_t size);
60
61clist * esmtp_address_list_new();
62int esmtp_address_list_add(clist * list, char * address,
63 int notify, char * orcpt);
64void esmtp_address_list_free(clist * l);
65
66clist * smtp_address_list_new();
67int smtp_address_list_add(clist * list, char * address);
68void smtp_address_list_free(clist * l);
69
70#ifdef __cplusplus
71}
72#endif
73
74#endif
diff --git a/libetpan/src/low-level/smtp/mailsmtp_socket.c b/libetpan/src/low-level/smtp/mailsmtp_socket.c
new file mode 100644
index 0000000..6b8d81a
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_socket.c
@@ -0,0 +1,99 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailsmtp_socket.h"
37
38#include "mailsmtp.h"
39
40#include "connect.h"
41#include <netinet/in.h>
42#include <unistd.h>
43
44#define DEFAULT_SMTP_PORT 25
45#define SERVICE_NAME_SMTP "smtp"
46#define SERVICE_TYPE_TCP "tcp"
47
48int mailsmtp_socket_connect(mailsmtp * session,
49 const char * server, uint16_t port)
50{
51 int s;
52 mailstream * stream;
53
54 if (port == 0) {
55 port = mail_get_service_port(SERVICE_NAME_SMTP, SERVICE_TYPE_TCP);
56 if (port == 0)
57 port = DEFAULT_SMTP_PORT;
58 port = ntohs(port);
59 }
60
61 /* Connection */
62
63 s = mail_tcp_connect(server, port);
64 if (s == -1)
65 return MAILSMTP_ERROR_CONNECTION_REFUSED;
66
67 stream = mailstream_socket_open(s);
68 if (stream == NULL) {
69 close(s);
70 return MAILSMTP_ERROR_MEMORY;
71 }
72
73 return mailsmtp_connect(session, stream);
74}
75
76int mailsmtp_socket_starttls(mailsmtp * session) {
77 int r;
78 int fd;
79 mailstream_low * low;
80 mailstream_low * new_low;
81
82 r = mailesmtp_starttls(session);
83 if (r != MAILSMTP_NO_ERROR)
84 return r;
85
86 low = mailstream_get_low(session->stream);
87 fd = mailstream_low_get_fd(low);
88 if (fd == -1)
89 return MAILSMTP_ERROR_STREAM;
90
91 new_low = mailstream_low_ssl_open(fd);
92 if (new_low == NULL)
93 return MAILSMTP_ERROR_STREAM;
94
95 mailstream_low_free(low);
96 mailstream_set_low(session->stream, new_low);
97
98 return MAILSMTP_NO_ERROR;
99}
diff --git a/libetpan/src/low-level/smtp/mailsmtp_socket.h b/libetpan/src/low-level/smtp/mailsmtp_socket.h
new file mode 100644
index 0000000..2726c1d
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_socket.h
@@ -0,0 +1,56 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_SOCKET_H
37
38#define MAILSMTP_SOCKET_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailsmtp_types.h>
47
48int mailsmtp_socket_connect(mailsmtp * session,
49 const char * server, uint16_t port);
50int mailsmtp_socket_starttls(mailsmtp * session);
51
52#ifdef __cplusplus
53}
54#endif
55
56#endif
diff --git a/libetpan/src/low-level/smtp/mailsmtp_ssl.c b/libetpan/src/low-level/smtp/mailsmtp_ssl.c
new file mode 100644
index 0000000..4a42326
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_ssl.c
@@ -0,0 +1,74 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mailsmtp_socket.h"
37
38#include "mailsmtp.h"
39
40#include "connect.h"
41#include <netinet/in.h>
42#include <unistd.h>
43
44#define DEFAULT_SMTPS_PORT 465
45#define SERVICE_NAME_SMTPS "smtps"
46#define SERVICE_TYPE_TCP "tcp"
47
48int mailsmtp_ssl_connect(mailsmtp * session,
49 const char * server, uint16_t port)
50{
51 int s;
52 mailstream * stream;
53
54 if (port == 0) {
55 port = mail_get_service_port(SERVICE_NAME_SMTPS, SERVICE_TYPE_TCP);
56 if (port == 0)
57 port = DEFAULT_SMTPS_PORT;
58 port = ntohs(port);
59 }
60
61 /* Connection */
62
63 s = mail_tcp_connect(server, port);
64 if (s == -1)
65 return MAILSMTP_ERROR_CONNECTION_REFUSED;
66
67 stream = mailstream_ssl_open(s);
68 if (stream == NULL) {
69 close(s);
70 return MAILSMTP_ERROR_CONNECTION_REFUSED;
71 }
72
73 return mailsmtp_connect(session, stream);
74}
diff --git a/libetpan/src/low-level/smtp/mailsmtp_ssl.h b/libetpan/src/low-level/smtp/mailsmtp_ssl.h
new file mode 100644
index 0000000..01f4683
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_ssl.h
@@ -0,0 +1,55 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_SSL_H
37
38#define MAILSMTP_SSL_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <inttypes.h>
45
46#include <libetpan/mailsmtp_types.h>
47
48int mailsmtp_ssl_connect(mailsmtp * session,
49 const char * server, uint16_t port);
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
diff --git a/libetpan/src/low-level/smtp/mailsmtp_types.h b/libetpan/src/low-level/smtp/mailsmtp_types.h
new file mode 100644
index 0000000..0aa2617
--- a/dev/null
+++ b/libetpan/src/low-level/smtp/mailsmtp_types.h
@@ -0,0 +1,126 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef MAILSMTP_TYPES_H
37
38#define MAILSMTP_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailstream.h"
45#include "mmapstring.h"
46
47enum {
48 MAILSMTP_NO_ERROR = 0,
49 MAILSMTP_ERROR_UNEXPECTED_CODE,
50 MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE,
51 MAILSMTP_ERROR_STREAM,
52 MAILSMTP_ERROR_HOSTNAME,
53 MAILSMTP_ERROR_NOT_IMPLEMENTED,
54 MAILSMTP_ERROR_ACTION_NOT_TAKEN,
55 MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION,
56 MAILSMTP_ERROR_IN_PROCESSING,
57 MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE,
58 MAILSMTP_ERROR_MAILBOX_UNAVAILABLE,
59 MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED,
60 MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND,
61 MAILSMTP_ERROR_USER_NOT_LOCAL,
62 MAILSMTP_ERROR_TRANSACTION_FAILED,
63 MAILSMTP_ERROR_MEMORY,
64 MAILSMTP_ERROR_AUTH_NOT_SUPPORTED,
65 MAILSMTP_ERROR_AUTH_LOGIN,
66 MAILSMTP_ERROR_AUTH_REQUIRED,
67 MAILSMTP_ERROR_AUTH_TOO_WEAK,
68 MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED,
69 MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE,
70 MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED,
71 MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE,
72 MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED,
73 MAILSMTP_ERROR_CONNECTION_REFUSED
74};
75
76enum {
77 MAILSMTP_AUTH_NOT_CHECKED = 0,
78 MAILSMTP_AUTH_CHECKED = 1,
79 MAILSMTP_AUTH_CRAM_MD5 = 2,
80 MAILSMTP_AUTH_PLAIN = 4,
81 MAILSMTP_AUTH_LOGIN = 8
82};
83
84enum {
85 MAILSMTP_ESMTP = 1,
86 MAILSMTP_ESMTP_EXPN = 2,
87 MAILSMTP_ESMTP_8BITMIME = 4,
88 MAILSMTP_ESMTP_SIZE = 8,
89 MAILSMTP_ESMTP_ETRN = 16,
90 MAILSMTP_ESMTP_STARTTLS = 32,
91 MAILSMTP_ESMTP_DSN = 64,
92};
93
94struct mailsmtp {
95 mailstream * stream;
96
97 size_t progr_rate;
98 progress_function * progr_fun;
99
100 char * response;
101
102 MMAPString * line_buffer;
103 MMAPString * response_buffer;
104
105 int esmtp; // contains flags MAILSMTP_ESMTP_*
106 int auth; // contains flags MAILSMTP_AUTH_*
107};
108
109typedef struct mailsmtp mailsmtp;
110
111#define MAILSMTP_DSN_NOTIFY_SUCCESS 1
112#define MAILSMTP_DSN_NOTIFY_FAILURE 2
113#define MAILSMTP_DSN_NOTIFY_DELAY 4
114#define MAILSMTP_DSN_NOTIFY_NEVER 8
115
116struct esmtp_address {
117 char * address;
118 int notify;
119 char * orcpt;
120};
121
122#ifdef __cplusplus
123}
124#endif
125
126#endif