diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-03-19 21:04:13 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-03-19 21:04:13 +0000 |
commit | 7cc856ea2f1808e98387ea66537ecbc6c3de2f88 (patch) | |
tree | 673b6eef191373f0607e5b9a9f79ad390e9bb970 /apps/netutils/smtp | |
parent | 7267882ebd0a6aa79cf88b7f42675804eaff1bcf (diff) | |
download | nuttx-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/Makefile | 94 | ||||
-rw-r--r-- | apps/netutils/smtp/smtp.c | 376 |
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); + } +} |