Return to fast_smtp.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libfast |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2010 Martin Willi ! 3: * Copyright (C) 2010 revosec AG ! 4: * ! 5: * This program is free software; you can redistribute it and/or modify it ! 6: * under the terms of the GNU General Public License as published by the ! 7: * Free Software Foundation; either version 2 of the License, or (at your ! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ! 9: * ! 10: * This program is distributed in the hope that it will be useful, but ! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! 13: * for more details. ! 14: */ ! 15: ! 16: #include "fast_smtp.h" ! 17: ! 18: #include <unistd.h> ! 19: #include <errno.h> ! 20: ! 21: #include <utils/debug.h> ! 22: ! 23: typedef struct private_fast_smtp_t private_fast_smtp_t; ! 24: ! 25: /** ! 26: * Private data of an fast_smtp_t object. ! 27: */ ! 28: struct private_fast_smtp_t { ! 29: ! 30: /** ! 31: * Public fast_smtp_t interface. ! 32: */ ! 33: fast_smtp_t public; ! 34: ! 35: /** ! 36: * file stream to SMTP server ! 37: */ ! 38: FILE *f; ! 39: }; ! 40: ! 41: /** ! 42: * Read the response code from an SMTP server ! 43: */ ! 44: static int read_response(private_fast_smtp_t *this) ! 45: { ! 46: char buf[256], *end; ! 47: int res = 0; ! 48: ! 49: while (TRUE) ! 50: { ! 51: if (!fgets(buf, sizeof(buf), this->f)) ! 52: { ! 53: return 0; ! 54: } ! 55: res = strtol(buf, &end, 10); ! 56: switch (*end) ! 57: { ! 58: case '-': ! 59: continue; ! 60: case ' ': ! 61: case '\0': ! 62: case '\n': ! 63: break; ! 64: default: ! 65: return 0; ! 66: } ! 67: break; ! 68: } ! 69: return res; ! 70: } ! 71: ! 72: /** ! 73: * write a SMTP command to the server, read response code ! 74: */ ! 75: static int write_cmd(private_fast_smtp_t *this, char *fmt, ...) ! 76: { ! 77: char buf[256]; ! 78: va_list args; ! 79: ! 80: va_start(args, fmt); ! 81: vsnprintf(buf, sizeof(buf), fmt, args); ! 82: va_end(args); ! 83: ! 84: if (fprintf(this->f, "%s\n", buf) < 1) ! 85: { ! 86: DBG1(DBG_LIB, "sending SMTP command failed"); ! 87: return 0; ! 88: } ! 89: return read_response(this); ! 90: } ! 91: ! 92: METHOD(fast_smtp_t, send_mail, bool, ! 93: private_fast_smtp_t *this, char *from, char *to, char *subject, char *fmt, ...) ! 94: { ! 95: va_list args; ! 96: ! 97: if (write_cmd(this, "MAIL FROM:<%s>", from) != 250) ! 98: { ! 99: DBG1(DBG_LIB, "SMTP MAIL FROM failed"); ! 100: return FALSE; ! 101: } ! 102: if (write_cmd(this, "RCPT TO:<%s>", to) != 250) ! 103: { ! 104: DBG1(DBG_LIB, "SMTP RCPT TO failed"); ! 105: return FALSE; ! 106: } ! 107: if (write_cmd(this, "DATA") != 354) ! 108: { ! 109: DBG1(DBG_LIB, "SMTP DATA failed"); ! 110: return FALSE; ! 111: } ! 112: ! 113: fprintf(this->f, "From: %s\n", from); ! 114: fprintf(this->f, "To: %s\n", to); ! 115: fprintf(this->f, "Subject: %s\n", subject); ! 116: fprintf(this->f, "\n"); ! 117: va_start(args, fmt); ! 118: vfprintf(this->f, fmt, args); ! 119: va_end(args); ! 120: fprintf(this->f, "\n.\n"); ! 121: return read_response(this) == 250; ! 122: } ! 123: ! 124: ! 125: METHOD(fast_smtp_t, destroy, void, ! 126: private_fast_smtp_t *this) ! 127: { ! 128: write_cmd(this, "QUIT"); ! 129: fclose(this->f); ! 130: free(this); ! 131: } ! 132: ! 133: /** ! 134: * See header ! 135: */ ! 136: fast_smtp_t *fast_smtp_create() ! 137: { ! 138: private_fast_smtp_t *this; ! 139: struct sockaddr_in addr = { ! 140: .sin_family = AF_INET, ! 141: .sin_port = htons(25), ! 142: .sin_addr = { ! 143: .s_addr = htonl(INADDR_LOOPBACK), ! 144: }, ! 145: }; ! 146: int s; ! 147: ! 148: INIT(this, ! 149: .public = { ! 150: .send_mail = _send_mail, ! 151: .destroy = _destroy, ! 152: }, ! 153: ); ! 154: ! 155: s = socket(AF_INET, SOCK_STREAM, 0); ! 156: if (s < 0) ! 157: { ! 158: DBG1(DBG_LIB, "opening SMTP socket failed: %s", strerror(errno)); ! 159: free(this); ! 160: return NULL; ! 161: } ! 162: if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) ! 163: { ! 164: DBG1(DBG_LIB, "connecting to SMTP server failed: %s", strerror(errno)); ! 165: close(s); ! 166: free(this); ! 167: return NULL; ! 168: } ! 169: this->f = fdopen(s, "a+"); ! 170: if (!this->f) ! 171: { ! 172: DBG1(DBG_LIB, "opening stream to SMTP server failed: %s", ! 173: strerror(errno)); ! 174: close(s); ! 175: free(this); ! 176: return NULL; ! 177: } ! 178: if (read_response(this) != 220 || ! 179: write_cmd(this, "EHLO localhost") != 250) ! 180: { ! 181: DBG1(DBG_LIB, "SMTP EHLO failed"); ! 182: fclose(this->f); ! 183: free(this); ! 184: return NULL; ! 185: } ! 186: return &this->public; ! 187: }