summaryrefslogtreecommitdiff
path: root/src/tools/anopesmtp.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2010-10-31 20:47:34 -0400
committerAdam <Adam@anope.org>2010-10-31 20:47:34 -0400
commite3f368f67b95438f39c0f459505af0e19ad364ad (patch)
tree0eba7020e2c95ef631049d97669ee4e7adffc239 /src/tools/anopesmtp.cpp
parent2170823059c176a79efd5e99fcfa53524c2d5536 (diff)
Fixed replacing %R's in email messages and fixed anopesmtp to really work
Diffstat (limited to 'src/tools/anopesmtp.cpp')
-rw-r--r--src/tools/anopesmtp.cpp258
1 files changed, 127 insertions, 131 deletions
diff --git a/src/tools/anopesmtp.cpp b/src/tools/anopesmtp.cpp
index aedbee725..78e0759ac 100644
--- a/src/tools/anopesmtp.cpp
+++ b/src/tools/anopesmtp.cpp
@@ -12,89 +12,104 @@
* *nix port by Trystan Scott Lee <trystan@nomadirc.net>
*/
-#include "smtp.h"
+#include "sysconf.h"
-static FILE *logfile;
-static int curday = 0;
-
-/*************************************************************************/
-
-static int get_logname(std::string &name, struct tm *tm = NULL)
-{
- char timestamp[32];
-
- if (!tm)
- {
- time_t t = time(NULL);
- tm = localtime(&t);
- }
+/* Some Linux boxes (or maybe glibc includes) require this for the
+ * prototype of strsignal(). */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
- strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm);
- name = std::string("logs/anopesmtp.") + timestamp;
- curday = tm->tm_yday;
+#include <string>
+#include <vector>
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <cerrno>
+#include <iostream>
+#include <fstream>
+
+#ifndef _WIN32
+# include <unistd.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# include <sys/socket.h>
+# include <arpa/inet.h>
+# include <sys/time.h>
+#else
+# include <winsock.h>
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
- return 1;
-}
+#include <sys/types.h>
+
+#ifdef _AIX
+extern int strcasecmp(const char *, const char *);
+extern int strncasecmp(const char *, const char *, size_t);
+# if 0 /* These break on some AIX boxes (4.3.1 reported). */
+extern int socket(int, int, int);
+extern int connect(int, struct sockaddr *, int);
+# endif
+#endif /* _AIX */
+
+/* Some SUN fixs */
+#ifdef __sun
+/* Solaris specific code, types that do not exist in Solaris'
+ * * sys/types.h
+ * **/
+# ifndef INADDR_NONE
+# define INADDR_NONE (-1)
+# endif
+#endif
/*************************************************************************/
-/* Close the log file. */
-
-void close_log()
-{
- if (!logfile)
- return;
- fclose(logfile);
- logfile = NULL;
-}
-
-/*************************************************************************/
+#ifdef _WIN32
+typedef SOCKET ano_socket_t;
+#define ano_sockclose(fd) closesocket(fd)
+#define ano_sockread(fd, buf, len) recv(fd, buf, len, 0)
+#define ano_sockwrite(fd, buf, len) send(fd, buf, len, 0)
+#else
+typedef int ano_socket_t;
+#define ano_sockclose(fd) close(fd)
+#define ano_sockread(fd, buf, len) read(fd, buf, len)
+#define ano_sockwrite(fd, buf, len) write(fd, buf, len)
+#define SOCKET_ERROR -1
+#endif
-static void remove_log()
+/* Data structures */
+struct smtp_message
{
- time_t t = time(NULL);
- t -= 2592000; // 30 days ago
- struct tm *tm = localtime(&t);
+ std::vector<std::string> smtp_headers;
+ std::vector<std::string> smtp_body;
+ std::string from;
+ std::string to;
+ ano_socket_t sock;
+};
- std::string name;
- if (!get_logname(name, tm))
- return;
- unlink(name.c_str());
-}
-/*************************************************************************/
+/* set this to 1 if you want to get a log otherwise it runs silent */
+int smtp_debug = 0;
-/* Open the log file. Return -1 if the log file could not be opened, else
- * return 0. */
+struct smtp_message smail;
-int open_log()
+static const char *get_logname(struct tm *tm = NULL)
{
- if (logfile)
- return 0;
-
- std::string name;
- if (!get_logname(name))
- return 0;
- logfile = fopen(name.c_str(), "w");
- return logfile ? 0 : -1;
-}
-
-/*************************************************************************/
-
-static void checkday()
-{
- time_t t = time(NULL);
- struct tm *tm = localtime(&t);
+ char timestamp[32];
- if (curday != tm->tm_yday)
+ if (!tm)
{
- close_log();
- remove_log();
- open_log();
+ time_t t = time(NULL);
+ tm = localtime(&t);
}
-}
-/*************************************************************************/
+ strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm);
+ std::string name = std::string("logs/anopesmtp.") + timestamp;
+ return name.c_str();
+}
/* Log stuff to the log file with a datestamp. Note that errno is
* preserved by this routine and log_perror().
@@ -102,14 +117,13 @@ static void checkday()
void alog(const char *fmt, ...)
{
- int errno_save = errno;
-
- if (!smtp_debug)
+ if (!smtp_debug || !fmt)
return;
- checkday();
+ std::fstream file;
+ file.open(get_logname(), std::ios_base::out);
- if (!fmt)
+ if (!file.is_open())
return;
va_list args;
@@ -120,22 +134,21 @@ void alog(const char *fmt, ...)
char buf[256];
strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S %Y] ", tm);
- if (logfile)
- {
- fputs(buf, logfile);
- vfprintf(logfile, fmt, args);
- fputc('\n', logfile);
- }
+ file << buf;
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ file << buf << std::endl;
+ va_end(args);
va_end(args);
- errno = errno_save;
+
+ file.close();
}
/*************************************************************************/
/* Remove a trailing \r\n */
-ci::string strip(const ci::string &buf)
+std::string strip(const std::string &buf)
{
- ci::string newbuf = buf;
+ std::string newbuf = buf;
char c = newbuf[newbuf.size() - 1];
while (c == '\n' || c == '\r')
{
@@ -148,14 +161,14 @@ ci::string strip(const ci::string &buf)
/*************************************************************************/
/* Is the buffer a header? */
-bool smtp_is_header(const ci::string &buf)
+bool smtp_is_header(const std::string &buf)
{
size_t tmp = buf.find(' ');
- if (tmp == ci::string::npos)
+ if (tmp == std::string::npos)
return false;
- if (buf[tmp + 1] == ':')
+ if (tmp > 0 && buf[tmp - 1] == ':')
return true;
return false;
}
@@ -163,12 +176,12 @@ bool smtp_is_header(const ci::string &buf)
/*************************************************************************/
/* Parse a header into a name and value */
-void smtp_parse_header(const ci::string &buf, ci::string &header, ci::string &value)
+void smtp_parse_header(const std::string &buf, std::string &header, std::string &value)
{
- ci::string newbuf = strip(buf);
+ std::string newbuf = strip(buf);
size_t space = newbuf.find(' ');
- if (space != ci::string::npos)
+ if (space != std::string::npos)
{
header = newbuf.substr(0, space);
value = newbuf.substr(space + 1);
@@ -183,7 +196,7 @@ void smtp_parse_header(const ci::string &buf, ci::string &header, ci::string &va
/*************************************************************************/
/* Have we reached the end of input? */
-bool smtp_is_end(const ci::string &buf)
+bool smtp_is_end(const std::string &buf)
{
if (buf[0] == '.')
if (buf[1] == '\r' || buf[1] == '\n')
@@ -195,14 +208,14 @@ bool smtp_is_end(const ci::string &buf)
/*************************************************************************/
/* Set who the email is to */
-void smtp_set_to(const ci::string &to)
+void smtp_set_to(const std::string &to)
{
- mail.to = to;
- size_t c = mail.to.rfind('<');
- if (c != ci::string::npos && c + 1 < mail.to.size())
+ smail.to = to;
+ size_t c = smail.to.rfind('<');
+ if (c != std::string::npos && c + 1 < smail.to.size())
{
- mail.to = mail.to.substr(c + 1);
- mail.to.erase(mail.to.end() - 1);
+ smail.to = smail.to.substr(c + 1);
+ smail.to.erase(smail.to.end() - 1);
}
}
@@ -213,7 +226,7 @@ int smtp_connect(const char *host, unsigned short port)
{
struct sockaddr_in addr;
- if ((mail.sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
+ if ((smail.sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
return 0;
if ((addr.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
@@ -225,9 +238,9 @@ int smtp_connect(const char *host, unsigned short port)
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port ? port : 25);
- if (connect(mail.sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(struct sockaddr_in)) == SOCKET_ERROR)
+ if (connect(smail.sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(struct sockaddr_in)) == SOCKET_ERROR)
{
- ano_sockclose(mail.sock);
+ ano_sockclose(smail.sock);
return 0;
}
@@ -239,12 +252,12 @@ int smtp_connect(const char *host, unsigned short port)
/* Send a line of text */
int smtp_send(const char *text)
{
- int result = ano_sockwrite(mail.sock, text, strlen(text));
+ int result = ano_sockwrite(smail.sock, text, strlen(text));
alog("SMTP: sent %s",text);
if (result == SOCKET_ERROR)
- ano_sockclose(mail.sock);
+ ano_sockclose(smail.sock);
return result;
}
@@ -257,10 +270,10 @@ int smtp_read(char *buf, int len)
int result;
memset(buf, 0, len);
- result = ano_sockread(mail.sock, buf, len);
+ result = ano_sockread(smail.sock, buf, len);
if (result == SOCKET_ERROR)
- ano_sockclose(mail.sock);
+ ano_sockclose(smail.sock);
return result;
}
@@ -272,10 +285,10 @@ int smtp_get_code(const std::string &text)
{
size_t tmp = text.find(' ');
- if (tmp == ci::string::npos)
+ if (tmp == std::string::npos)
return 0;
- return atol(text.c_str());
+ return atol(text.substr(0, tmp).c_str());
}
/*************************************************************************/
@@ -317,7 +330,7 @@ int smtp_send_email()
}
strcpy(buf, "MAIL FROM: <");
- strcat(buf, mail.from.c_str());
+ strcat(buf, smail.from.c_str());
strcat(buf, ">\r\n");
if (!smtp_send(buf))
@@ -337,7 +350,7 @@ int smtp_send_email()
return 0;
strcpy(buf, "RCPT TO: <");
- strcat(buf, mail.to.c_str());
+ strcat(buf, smail.to.c_str());
strcat(buf, ">\r\n");
if (!smtp_send(buf))
@@ -378,7 +391,7 @@ int smtp_send_email()
return 0;
}
- for (std::vector<ci::string>::const_iterator it = mail.smtp_headers.begin(), it_end = mail.smtp_headers.end(); it != it_end; ++it)
+ for (std::vector<std::string>::const_iterator it = smail.smtp_headers.begin(), it_end = smail.smtp_headers.end(); it != it_end; ++it)
if (!smtp_send(it->c_str()))
{
alog("SMTP: error writting to socket");
@@ -392,7 +405,7 @@ int smtp_send_email()
}
bool skip_done = false;
- for (std::vector<ci::string>::const_iterator it = mail.smtp_body.begin(), it_end = mail.smtp_body.end(); it != it_end; ++it)
+ for (std::vector<std::string>::const_iterator it = smail.smtp_body.begin(), it_end = smail.smtp_body.end(); it != it_end; ++it)
if (skip_done)
{
if (!smtp_send(it->c_str()))
@@ -418,19 +431,7 @@ int smtp_send_email()
void smtp_disconnect()
{
smtp_send("QUIT\r\n");
- ano_sockclose(mail.sock);
-}
-
-/*************************************************************************/
-
-void mail_cleanup()
-{
- mail.from.clear();
- mail.to.clear();
-
- mail.smtp_headers.clear();
-
- mail.smtp_body.clear();
+ ano_sockclose(smail.sock);
}
/*************************************************************************/
@@ -461,8 +462,6 @@ int main(int argc, char *argv[])
else
alog("SMTP: server %s port %d",server,port);
- memset(&mail, 0, sizeof(mail));
-
/* The WSAStartup function initiates use of WS2_32.DLL by a process. */
/* guessing we can skip it under *nix */
#ifdef _WIN32
@@ -477,15 +476,15 @@ int main(int argc, char *argv[])
{
if (smtp_is_header(buf) && !headers_done)
{
- mail.smtp_headers.push_back(strip(buf) + "\r\n");
- ci::string header, value;
+ smail.smtp_headers.push_back(strip(buf) + "\r\n");
+ std::string header, value;
smtp_parse_header(buf, header, value);
- if (header == "from")
+ if (header == "From:")
{
alog("SMTP: from: %s", value.c_str());
- mail.from = value;
+ smail.from = value;
}
- else if (header == "to")
+ else if (header == "To:")
{
alog("SMTP: to: %s", value.c_str());
smtp_set_to(value);
@@ -495,27 +494,24 @@ int main(int argc, char *argv[])
else
{
headers_done = true;
- mail.smtp_body.push_back(strip(buf) + "\r\n");
+ smail.smtp_body.push_back(strip(buf) + "\r\n");
}
}
else
- mail.smtp_body.push_back(strip(buf) + "\r\n");
+ smail.smtp_body.push_back(strip(buf) + "\r\n");
}
if (!smtp_connect(server, port))
{
alog("SMTP: failed to connect to %s:%d", server, port);
- mail_cleanup();
return 0;
}
if (!smtp_send_email())
{
alog("SMTP: error during sending of mail");
- mail_cleanup();
return 0;
}
smtp_disconnect();
- mail_cleanup();
return 1;
}