// SMTPSend.c
//
// Created by Dr. Rolf Jansen on 2011-05-04.
// Copyright 2011 InstantWare - Dr. Rolf Jansen. All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THIS SOFTWARE IS PROVIDED BY InstantWare - Dr. Rolf Jansen "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 InstantWare - Dr. Rolf Jansen
// 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.
//
// cc SMTPSend.c -std=c99 -Os -g0 -o /usr/local/bin/SMTPSend
// Standard C includes
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
// header files which must be included for
// high level DNS services and socket connections
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// constants
#define defaultBufferSize 4096
short doSMTPTransaction(int smtpSocket, char *sendBuffer, long sendBufferSize, char *receiveBuffer)
{
long receiveSize = 0;
if (sendBuffer && send(smtpSocket, sendBuffer, sendBufferSize, 0) == -1)
return 1000;
else if (receiveBuffer && (receiveSize = recv(smtpSocket, receiveBuffer, defaultBufferSize - 1, 0)) < 0)
return 2000;
if (receiveSize != 0)
{
receiveBuffer[receiveSize] = '\0';
return strtol(receiveBuffer, NULL, 10);
}
else
return 0;
}
// argv[1]: fully qualified sender address
// argv[2..n]: fully qualified recipient addresses
int main(int argc, const char *argv[])
{
int i, smtpCode = 0, resultCode = 1;
long smtpSocket, sendBufferSize;
char c = 0;
char transferBuffer[defaultBufferSize];
struct sockaddr_in address;
struct hostent *host = NULL;
char *smtpRelayHostName = "smtp.relay.dom"; // replace with the IP or address of the relay server
char *smtpAuthLoginID = "dXNlcm5hbWUK\r\n"; // replace with your base 64 encoded SMTP login ID
char *smtpAuthPassword = "cGFzc3dvcmQK\r\n"; // replace with your base 64 encoded SMTP auth password
if (!inet_aton(smtpRelayHostName, &address.sin_addr))
if (host = gethostbyname(smtpRelayHostName))
address.sin_addr = *(struct in_addr*)host->h_addr;
else
goto finish;
address.sin_port = htons(25); // if 25 is blocked, then put the alternate smtp port 587 here
address.sin_family = AF_INET;
if ((smtpSocket = socket(AF_INET, SOCK_STREAM, 0)) != -1)
{
if (connect(smtpSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) != -1)
{
if ((smtpCode = doSMTPTransaction(smtpSocket, NULL, 0, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "EHLO %s\r\n", argv[1]);
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
sendBufferSize = sprintf(transferBuffer, "AUTH LOGIN\r\n");
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 334)
goto closeSession;
if ((smtpCode = doSMTPTransaction(smtpSocket, smtpAuthLoginID, strlen(smtpAuthLoginID), transferBuffer)) != 334)
goto closeSession;
if ((smtpCode = doSMTPTransaction(smtpSocket, smtpAuthPassword, strlen(smtpAuthPassword), transferBuffer)) != 235)
goto closeSession;
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "MAIL FROM:<%s>\r\n", argv[1]);
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
for (i = 2; i < argc; i++)
{
sendBufferSize = snprintf(transferBuffer, defaultBufferSize, "RCPT TO:<%s>\r\n", argv[i]);
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) > 299)
goto closeSession;
}
sendBufferSize = sprintf(transferBuffer, "DATA\r\n");
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) != 354)
goto closeSession;
while (c != EOF)
{
for (i = 0; i < defaultBufferSize && (c = fgetc(stdin)) != EOF; i++)
transferBuffer[i] = c;
smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, i, NULL);
}
sendBufferSize = sprintf(transferBuffer, "\r\n.\r\nQUIT\r\n");
if ((smtpCode = doSMTPTransaction(smtpSocket, transferBuffer, sendBufferSize, transferBuffer)) == 250);
resultCode = 0;
closeSession:
close(smtpSocket);
}
}
finish:
if (resultCode)
syslog(LOG_ERR, "SMTPSend from %s to %s failed.", argv[1], argv[2]);
return resultCode;
}