|
XML * NOTIFY_smtp_send (WFTK_ADAPTOR * ad, va_list args)
{
char * to;
char * from;
char * subject;
char * textview;
char * htmlview;
char hostname[64];
struct hostent *server;
char line[1024];
char buf[1024];
char * mark;
XML * lookup;
int bytes;
#ifdef WINDOWS
SOCKET sock;
# define SOCK_BAD (sock == INVALID_SOCKET)
# define CLOSESOCK (closesocket (sock))
WSADATA wsa;
#else
int sock;
# define SOCK_BAD (sock < 0)
# define CLOSESOCK (close (sock))
#endif
struct sockaddr_in name;
if (args) to = va_arg (args, char *);
if (!to) {
xml_set (ad->parms, "error", "No recipient specified.");
return (XML *) 0;
}
if (args) from = va_arg (args, char *);
if (!from) {
xml_set (ad->parms, "error", "No sender specified.");
return (XML *) 0;
}
if (args) subject = va_arg (args, char *);
if (args) textview = va_arg (args, char *);
if (args) htmlview = va_arg (args, char *);
sprintf (line, "SMTP requested to: (%s) from: (%s) subject: (%s)", to, from, subject);
(ad->log) (ad->session, ad, 5, line);
#ifdef WINDOWS
WSAStartup (MAKEWORD (1, 0), &wsa);
#endif
gethostname (hostname, sizeof(hostname));
server = gethostbyname (xml_attrval (ad->parms, "server"));
if (!server) {
/* 2005-02-16 - if there's no mailserver specified, we want to figure out a direct-to-MX server to use. */
/* 2005-02-22 - So I wrote the DNS action adaptor, which calls res_query so you don't have to. */
mark = strchr (to, '@');
if (mark) {
mark++;
lookup = xml_create ("action");
xml_set (lookup, "handler", "dns");
xml_set (lookup, "action", "lookup");
xml_set (lookup, "type", "mx");
xmlobj_set (lookup, NULL, "name", mark);
repos_action_do (ad->session, lookup);
xml_set_nodup (lookup, "mx_server", xmlobj_get (lookup, NULL, "an(0).data"));
if (*xml_attrval (lookup, "mx_server")) {
sprintf (line, "MX server established as %s", xml_attrval (lookup, "mx_server"));
(ad->log) (ad->session, ad, 5, line);
} else {
(ad->log) (ad->session, ad, 2, "Unable to find MX server");
}
server = gethostbyname (xml_attrval (lookup, "mx_server"));
xml_free (lookup);
}
}
if (!server) {
xml_set (ad->parms, "error", "Unable to resolve server name.");
return (XML *) 0;
}
sock = socket (AF_INET, SOCK_STREAM, 0);
if (SOCK_BAD) {
xml_set (ad->parms, "error", "Unable to allocate socket.");
return (XML *) 0;
}
memset (&name, 0, sizeof (struct sockaddr_in));
name.sin_family = AF_INET;
name.sin_port = htons (25);
memcpy (&name.sin_addr, server->h_addr_list[0], server->h_length);
if (connect(sock, (struct sockaddr *) &name, sizeof (struct sockaddr)) < 0) {
xml_setf (ad->parms, "error", "Unable to connect to server %s.", server);
CLOSESOCK;
return (XML *) 0;
}
memset (line, 0, sizeof(line));
bytes = recv (sock, line, sizeof(line), 0);
sprintf (line, "HELO %s", hostname);
(ad->log) (ad->session, ad, 5, line);
send (sock, line, strlen(line), 0); /* Send HELO. */
send (sock, "\r\n", 2, 0);
memset (line, 0, sizeof(line));
bytes = recv (sock, line, sizeof(line), 0);
if (bytes < 4 || strncmp (line, "250 ", 4)) {
xml_setf (ad->parms, "error", "Server refused connection. (%s)", line);
CLOSESOCK;
return (XML *) 0;
}
mark = strchr (from, '<');
if (mark) {
strcpy (buf, mark+1);
mark = strchr (buf, '>');
if (mark) *mark = '\0';
} else {
strcpy (buf, from);
}
sprintf (line, "MAIL FROM: <%s>", buf);
(ad->log) (ad->session, ad, 5, line);
send (sock, line, strlen(line), 0);
send (sock, "\r\n", 2, 0);
memset (line, 0, sizeof(line));
bytes = recv (sock, line, sizeof(line), 0);
if (bytes < 4 || strncmp (line, "250 ", 4)) {
xml_setf (ad->parms, "error", "Failure on MAIL FROM: (%s)", line);
CLOSESOCK;
return (XML *) 0;
}
mark = strchr (to, '<');
if (mark) {
strcpy (buf, mark+1);
mark = strchr (buf, '>');
if (mark) *mark = '\0';
} else {
strcpy (buf, to);
}
sprintf (line, "RCPT TO: <%s>", buf);
(ad->log) (ad->session, ad, 5, line);
send (sock, line, strlen(line), 0);
send (sock, "\r\n", 2, 0);
memset (line, 0, sizeof(line));
bytes = recv (sock, line, sizeof(line), 0);
if (bytes < 4 || strncmp (line, "250 ", 4)) {
xml_setf (ad->parms, "error", "Failure on RCPT TO: (%s)", line);
CLOSESOCK;
return (XML *) 0;
}
send (sock, "DATA\r\n", 6, 0);
bytes = recv (sock, line, sizeof(line), 0);
sprintf (line, "From: %s\n", from); send (sock, line, strlen(line), 0);
sprintf (line, "To: %s\n", to); send (sock, line, strlen(line), 0);
sprintf (line, "Subject: %s\n", subject); send (sock, line, strlen(line), 0);
if (textview && !htmlview) {
strcpy (line, "Content-Type: text/plain\n"); send (sock, line, strlen(line), 0);
send (sock, "\n", 1, 0);
send (sock, textview, strlen(textview), 0);
send (sock, "\n", 1, 0);
} else if (!textview && htmlview) {
strcpy (line, "Content-Type: text/html\n"); send (sock, line, strlen(line), 0);
send (sock, "\n", 1, 0);
send (sock, htmlview, strlen(htmlview), 0);
send (sock, "\n", 1, 0);
} else if (textview) {
strcpy (line, "Content-Type: multipart/alternative;\n boundary=\"----------wftk7897234hi_mom\""); send (sock, line, strlen(line), 0);
send (sock, "\n", 1, 0);
strcpy (line, "This is a multi-part message in MIME format.\n------------wftk7897234hi_mom\n"); send (sock, line, strlen(line), 0);
strcpy (line, "Content-Type: text/plain;\n\n"); send (sock, line, strlen(line), 0);
send (sock, textview, strlen(textview), 0);
strcpy (line, "------------wftk7897234hi_mom\n"); send (sock, line, strlen(line), 0);
strcpy (line, "Content-Type: text/html;\n\n"); send (sock, line, strlen(line), 0);
send (sock, htmlview, strlen(htmlview), 0);
strcpy (line, "------------wftk7897234hi_mom--\n"); send (sock, line, strlen(line), 0);
} else {
send (sock, "\r\n", 2, 0);
}
send (sock, ".\r\n", 3, 0);
memset (line, 0, sizeof(line));
bytes = recv (sock, line, sizeof(line), 0);
if (bytes < 4 || strncmp (line, "250 ", 4)) {
xml_setf (ad->parms, "error", "Message not accepted by server. (%s)", line);
CLOSESOCK;
return (XML *) 0;
}
send (sock, "QUIT\r\n", 6, 0);
bytes = recv (sock, line, sizeof(line), 0);
CLOSESOCK;
return (XML *) 0;
}
|