/* * Copyright (c) 2007 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Simple SMTP client routines. */ #include #include #include #include #include #include #include #include #include "smtp.h" #include "pathnames.h" static int SMTP_Expect(FILE *f, const char *code) { char *buf, *lbuf = NULL; size_t len; int rv = 0; if ((buf = fgetln(f, &len)) == NULL) { fprintf(stderr, "EOF from server\n"); return (0); } if (buf[len-1] == '\n') { buf[len-1] = '\0'; } else { if ((lbuf = malloc(len+1)) == NULL) { fprintf(stderr, "malloc linebuf\n"); return (0); } memcpy(lbuf, buf, len); lbuf[len] = '\0'; buf = lbuf; } if (code[0] != buf[0]) { fprintf(stderr, "Server returned \"%s\" (was expecting %s)\n", buf, code); rv = 0; } if (lbuf != NULL) { free(lbuf); } return (1); } /* Inject a message via SMTP */ int SMTP_Inject(const char *msg, size_t msgLen, const char *from, const char *rcpt, const char *host, const char *port) { struct addrinfo hints, *res, *res0; const char *cause = NULL; int rv, s; FILE *f; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((rv = getaddrinfo(host, port, &hints, &res0)) != 0) { fprintf(stderr, "%s:%s: %s\n", host, port, gai_strerror(rv)); return (-1); } for (s = -1, res = res0; res != NULL; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) { cause = "socket"; continue; } if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { cause = "connect"; close(s); s = -1; continue; } break; } if (s == -1) { fprintf(stderr, "%s: %s\n", cause, strerror(errno)); goto fail_addr; } if ((f = fdopen(s, "w+")) == NULL) { fprintf(stderr, "fdopen: %s\n", strerror(errno)); goto fail; } if (setvbuf(f, NULL, _IOLBF, 0) == EOF) { printf("setvbuf failed\n"); } if (!SMTP_Expect(f, "2")) { goto fail; } fputs("HELO [127.0.0.1]\n", f); if (!SMTP_Expect(f, "2")) { goto fail; } fputs("MAIL FROM:<", f); fputs(from, f); fputs(">\n", f); if (!SMTP_Expect(f, "2")) { goto fail; } fputs("RCPT TO:<", f); fputs(rcpt, f); fputs(">\n", f); if (!SMTP_Expect(f, "2")) { goto fail; } fputs("DATA\n", f); if (!SMTP_Expect(f, "3")) { goto fail; } fputs(msg, f); fputs("\r\n.\r\n", f); if (!SMTP_Expect(f, "2")) { goto fail; } close(s); freeaddrinfo(res0); return (0); fail: close(s); fail_addr: freeaddrinfo(res0); return (-1); }