summaryrefslogtreecommitdiff
path: root/apps/netutils/smtp
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-19 21:04:13 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-19 21:04:13 +0000
commit7cc856ea2f1808e98387ea66537ecbc6c3de2f88 (patch)
tree673b6eef191373f0607e5b9a9f79ad390e9bb970 /apps/netutils/smtp
parent7267882ebd0a6aa79cf88b7f42675804eaff1bcf (diff)
downloadnuttx-7cc856ea2f1808e98387ea66537ecbc6c3de2f88.tar.gz
nuttx-7cc856ea2f1808e98387ea66537ecbc6c3de2f88.tar.bz2
nuttx-7cc856ea2f1808e98387ea66537ecbc6c3de2f88.zip
Move nuttx/netutils to apps/netutils
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3401 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'apps/netutils/smtp')
-rw-r--r--apps/netutils/smtp/Makefile94
-rw-r--r--apps/netutils/smtp/smtp.c376
2 files changed, 470 insertions, 0 deletions
diff --git a/apps/netutils/smtp/Makefile b/apps/netutils/smtp/Makefile
new file mode 100644
index 000000000..05ace5c53
--- /dev/null
+++ b/apps/netutils/smtp/Makefile
@@ -0,0 +1,94 @@
+############################################################################
+# apps/netutils/smtp/Makefile
+#
+# Copyright (C) 2011 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# 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.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# 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
+# COPYRIGHT OWNER 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.
+#
+############################################################################
+
+-include $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# SMTP Library
+
+ASRCS =
+CSRCS =
+
+ifeq ($(CONFIG_NET_TCP),y)
+CSRCS += smtp.c
+endif
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+BIN = ../../libapps$(LIBEXT)
+
+ROOTDEPPATH = --dep-path .
+
+# Common build
+
+VPATH =
+
+all: .built
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+$(BIN): $(OBJS)
+ @( for obj in $(OBJS) ; do \
+ $(call ARCHIVE, $@, $${obj}); \
+ done ; )
+ @touch .built
+
+.built: $(BIN)
+
+.depend: Makefile $(SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) \
+ $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+# Register application
+depend: .depend
+
+clean:
+ @rm -f $(BIN) *.o *~ .*.swp .built
+ $(call CLEAN)
+
+distclean: clean
+ @rm -f Make.dep .depend
+
+-include Make.dep
diff --git a/apps/netutils/smtp/smtp.c b/apps/netutils/smtp/smtp.c
new file mode 100644
index 000000000..d758c6f6b
--- /dev/null
+++ b/apps/netutils/smtp/smtp.c
@@ -0,0 +1,376 @@
+/****************************************************************************
+ * apps/netutitls/smtp/smtp.c
+ * smtp SMTP E-mail sender
+ *
+ * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Heavily leveraged from uIP 1.0 which also has a BSD-like license:
+ *
+ * The Simple Mail Transfer Protocol (SMTP) as defined by RFC821 is
+ * the standard way of sending and transfering e-mail on the
+ * Internet. This simple example implementation is intended as an
+ * example of how to implement protocols in uIP, and is able to send
+ * out e-mail but has not been extensively tested.
+ *
+ * Author: Adam Dunkels <adam@dunkels.com>
+ * Copyright (c) 2004, Adam Dunkels.
+ * 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.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <semaphore.h>
+#include <sys/socket.h>
+
+#include <net/uip/uip.h>
+#include <apps/netutils/smtp.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define SMTP_INPUT_BUFFER_SIZE 512
+
+#define ISO_nl 0x0a
+#define ISO_cr 0x0d
+
+#define ISO_period 0x2e
+
+#define ISO_2 0x32
+#define ISO_3 0x33
+#define ISO_4 0x34
+#define ISO_5 0x35
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure represents the state of a single SMTP transaction */
+
+struct smtp_state
+{
+ uint8_t state;
+ bool connected;
+ sem_t sem;
+ uip_ipaddr_t smtpserver;
+ const char *localhostname;
+ const char *to;
+ const char *cc;
+ const char *from;
+ const char *subject;
+ const char *msg;
+ int msglen;
+ int sentlen;
+ int textlen;
+ int sendptr;
+ char buffer[SMTP_INPUT_BUFFER_SIZE];
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const char g_smtp220[] = "220";
+static const char g_smtpcrnlperiodcrnl[] = "\r\n.\r\n";
+static const char g_smtpdata[] = "DATA\r\n";
+static const char g_smtpfrom[] = "From: ";
+static const char g_smtphelo[] = "HELO ";
+static const char g_smtpmailfrom[] = "MAIL FROM: ";
+static const char g_smtpquit[] = "QUIT\r\n";
+static const char g_smtprcptto[] = "RCPT TO: ";
+static const char g_smtpsubject[] = "Subject: ";
+static const char g_smtpto[] = "To: ";
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static inline int smtp_send_message(int sockfd, struct smtp_state *psmtp)
+{
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (strncmp(psmtp->buffer, g_smtp220, strlen(g_smtp220)) != 0)
+ {
+ return ERROR;
+ }
+
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", g_smtphelo, psmtp->localhostname);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (psmtp->buffer[0] != ISO_2)
+ {
+ return ERROR;
+ }
+
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", g_smtpmailfrom, psmtp->from);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (psmtp->buffer[0] != ISO_2)
+ {
+ return ERROR;
+ }
+
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", g_smtprcptto, psmtp->to);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (psmtp->buffer[0] != ISO_2)
+ {
+ return ERROR;
+ }
+
+ if (psmtp->cc != 0)
+ {
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", g_smtprcptto, psmtp->cc);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (psmtp->buffer[0] != ISO_2)
+ {
+ return ERROR;
+ }
+ }
+
+ if (send(sockfd, g_smtpdata, strlen(g_smtpdata), 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (psmtp->buffer[0] != ISO_3)
+ {
+ return ERROR;
+ }
+
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", g_smtpto, psmtp->to);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (psmtp->cc != 0)
+ {
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", g_smtpto, psmtp->cc);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
+ }
+
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", g_smtpfrom, psmtp->from);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
+
+ snprintf(psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, "%s%s\r\n", g_smtpsubject, psmtp->subject);
+ if (send(sockfd, psmtp->buffer, strlen(psmtp->buffer), 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (send(sockfd, psmtp->msg, psmtp->msglen, 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (send(sockfd, g_smtpcrnlperiodcrnl, strlen(g_smtpcrnlperiodcrnl), 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (recv(sockfd, psmtp->buffer, SMTP_INPUT_BUFFER_SIZE, 0) < 0)
+ {
+ return ERROR;
+ }
+
+ if (psmtp->buffer[0] != ISO_2)
+ {
+ return ERROR;
+ }
+
+ if (send(sockfd, g_smtpquit, strlen(g_smtpquit), 0) < 0)
+ {
+ return ERROR;
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* Specificy an SMTP server and hostname.
+ *
+ * This function is used to configure the SMTP module with an SMTP server and
+ * the hostname of the host.
+ *
+ * lhostname - The hostname of the local, uIP host.
+ *
+ * paddr - A pointer to the IP address of the SMTP server to be
+ * configured.
+ */
+
+void smtp_configure(void *handle, const char *lhostname,
+ const uip_ipaddr_t *paddr)
+{
+ struct smtp_state *psmtp = (struct smtp_state *)handle;
+ psmtp->localhostname = lhostname;
+ uip_ipaddr_copy(psmtp->smtpserver, paddr);
+}
+
+/* Send an e-mail.
+ *
+ * to - The e-mail address of the receiver of the e-mail.
+ * cc - The e-mail address of the CC: receivers of the e-mail.
+ * from - The e-mail address of the sender of the e-mail.
+ * subject - The subject of the e-mail.
+ * msg - The actual e-mail message.
+ * msglen - The length of the e-mail message.
+ */
+
+int smtp_send(void *handle, const char *to, const char *cc, const char *from,
+ const char *subject, const char *msg, int msglen)
+{
+ struct smtp_state *psmtp = (struct smtp_state *)handle;
+ struct sockaddr_in server;
+ int sockfd;
+ int ret;
+
+ /* Setup */
+
+ psmtp->connected = true;
+ psmtp->to = to;
+ psmtp->cc = cc;
+ psmtp->from = from;
+ psmtp->subject = subject;
+ psmtp->msg = msg;
+ psmtp->msglen = msglen;
+
+ /* Create a socket */
+
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockfd < 0)
+ {
+ return ERROR;
+ }
+
+ /* Connect to server. First we have to set some fields in the
+ * 'server' structure. The system will assign me an arbitrary
+ * local port that is not in use.
+ */
+
+ server.sin_family = AF_INET;
+ memcpy(&server.sin_addr.s_addr, &psmtp->smtpserver, sizeof(in_addr_t));
+ server.sin_port = HTONS(25);
+
+ if (connect(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0)
+ {
+ close(sockfd);
+ return ERROR;
+ }
+
+ /* Send the message */
+
+ ret = smtp_send_message(sockfd, psmtp);
+
+ close(sockfd);
+ return ret;
+}
+
+void *smtp_open(void)
+{
+ /* Allocate the handle */
+
+ struct smtp_state *psmtp = (struct smtp_state *)malloc(sizeof(struct smtp_state));
+ if (psmtp)
+ {
+ /* Initialize the handle */
+
+ memset(psmtp, 0, sizeof(struct smtp_state));
+ (void)sem_init(&psmtp->sem, 0, 0);
+ }
+ return (void*)psmtp;
+}
+
+void smtp_close(void *handle)
+{
+ struct smtp_state *psmtp = (struct smtp_state *)handle;
+ if (psmtp)
+ {
+ sem_destroy(&psmtp->sem);
+ free(psmtp);
+ }
+}