Ejemplo n.º 1
0
int sendmail_main(int argc, char *argv[])
{
  struct in_addr addr;
#if defined(CONFIG_EXAMPLES_SENDMAIL_NOMAC)
  uint8_t mac[IFHWADDRLEN];
#endif
  void *handle;

  printf("sendmail: To: %s\n", g_recipient);
  printf("sendmail: From: %s\n", g_sender);
  printf("sendmail: Subject: %s\n", g_subject);
  printf("sendmail: Body: %s\n", g_msg_body);

/* Many embedded network interfaces must have a software assigned MAC */

#ifdef CONFIG_EXAMPLES_SENDMAIL_NOMAC
  mac[0] = 0x00;
  mac[1] = 0xe0;
  mac[2] = 0xde;
  mac[3] = 0xad;
  mac[4] = 0xbe;
  mac[5] = 0xef;
  netlib_setmacaddr("eth0", mac);
#endif

  /* Set up our host address */

  addr.s_addr = HTONL(CONFIG_EXAMPLES_SENDMAIL_IPADDR);
  netlib_sethostaddr("eth0", &addr);

  /* Set up the default router address */

  addr.s_addr = HTONL(CONFIG_EXAMPLES_SENDMAIL_DRIPADDR);
  netlib_setdraddr("eth0", &addr);

  /* Setup the subnet mask */

  addr.s_addr = HTONL(CONFIG_EXAMPLES_SENDMAIL_NETMASK);
  netlib_setnetmask("eth0", &addr);

  /* Then send the mail */

  net_ipaddr(addr.s_addr, 127, 0, 0, 1);
  handle = smtp_open();
  if (handle)
    {
      smtp_configure(handle, g_host_name, &addr.s_addr);
      smtp_send(handle, g_recipient, NULL, g_sender, g_subject,
                g_msg_body, strlen(g_msg_body));
      smtp_close(handle);
    }
  return 0;
}
Ejemplo n.º 2
0
static err_t
smtp_tcp_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
  LWIP_UNUSED_ARG(arg);

  if (err == ERR_OK) {
    LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_connected: Waiting for 220\n"));
  } else {
    LWIP_DEBUGF(SMTP_DEBUG_WARN, ("smtp_connected: %d\n", (int)err));
    smtp_close(arg, pcb, SMTP_RESULT_ERR_CONNECT, 0, err);
  }
  return ERR_OK;
}
Ejemplo n.º 3
0
/** Raw API TCP recv callback */
static err_t
smtp_tcp_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
  LWIP_UNUSED_ARG(err);
  if (p != NULL) {
    tcp_recved(pcb, p->tot_len);
    smtp_process(arg, pcb, p);
  } else {
    LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("smtp_tcp_recv: connection closed by remote host\n"));
    smtp_close(arg, pcb, SMTP_RESULT_ERR_CLOSED, 0, err);
  }
  return ERR_OK;
}
Ejemplo n.º 4
0
static err_t
smtp_tcp_connected(void *arg, struct altcp_pcb *pcb, err_t err)
{
  LWIP_UNUSED_ARG(arg);

  if (err == ERR_OK) {
    LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_connected: Waiting for 220\n"));
  } else {
    /* shouldn't happen, but we still check 'err', only to be sure */
    LWIP_DEBUGF(SMTP_DEBUG_WARN, ("smtp_connected: %d\n", (int)err));
    smtp_close((struct smtp_session*)arg, pcb, SMTP_RESULT_ERR_CONNECT, 0, err);
  }
  return ERR_OK;
}
Ejemplo n.º 5
0
void smtp_client::close()
{
	if (client_)
	{
		// 将 SMTP_CLIENT 对象的流置空,以避免内部再次释放,
		// 因为该流对象会在下面 stream_.close() 时被释放
		client_->conn = NULL;
		smtp_close(client_);
		client_ = NULL;
	}

	// 当 socket 流对象打开着,则关闭之,同时将依附于其的 SSL 对象释放
	if (stream_.opened())
		stream_.close();

	// 重置连接是否被重用的状态
	reuse_ = false;
}
Ejemplo n.º 6
0
int
return_mail(FILE *fp, email_hdr_t *eh, int flags, char *errstr)
{
	int i;
	int len;
	FILE *nfp;
	char *p;
	char *incl;
	char *bincl;
	char *subj;
	char **sig;
	char **body;
	char *copy_addr;
	char *rtn_addr;
	char *tret;
	char *echo;
	char buf[CDDBBUFSIZ];
	char subj_buf[CDDBBUFSIZ];
	struct stat sbuf;
	int charset = -1;

	/* Create a temporary file for the mail. */
	tret = cddbd_mktemp();

	if(flags & MF_FAIL) {
		strncpy(buf, errstr, sizeof(buf));
		buf[sizeof(buf) - 1] = '\0';

		if((p = (char *)strchr(buf, '\n')) != NULL)
			*p = '\0';
	}

	/* Return address is currently always the admin. */
	rtn_addr = admin_email;

	switch(eh->eh_class) {
	case EC_COMMAND:
		/* Command response. */
		if(flags & MF_FAIL) {
			cddbd_log(LOG_ERR | LOG_MAIL,
			    "Email command failed: %s", buf);

			cddbd_snprintf(subj_buf, sizeof(subj_buf),
			    cmd_rej_subj, eh->eh_serial);

			sig = gen_rej_sig;
			body = gen_rej_body;
			incl = gen_incl;
			bincl = gen_incl_blank;
			copy_addr = bounce_email;
		}
		else {
			cddbd_snprintf(subj_buf, sizeof(subj_buf),
			    cmd_ok_subj, eh->eh_serial);

			sig = 0;
			body = 0;
			incl = null_incl;
			bincl = null_incl_blank;
			copy_addr = 0;
		}

		subj = subj_buf;

		break;

	case EC_SUBMIT:
		/* We only send mail for rejections and test submissions. */
		if(flags & MF_FAIL) {
			if(flags & MF_TEST) {
				cddbd_log(LOG_ERR | LOG_MAIL,
				    "Test email submission failed: %s", buf);

				subj = test_rej_subj;
			}
			else {
				cddbd_log(LOG_ERR | LOG_MAIL,
				    "Email submission failed: %s", buf);

				subj = sub_rej_subj;
			}

			sig = gen_rej_sig;
			body = sub_rej_body;
			copy_addr = bounce_email;
		}
		else {
			sig = test_ok_sig;
			body = test_ok_body;
			subj = test_ok_subj;
			copy_addr = test_email;
		}

		incl = gen_incl;
		bincl = gen_incl_blank;

		charset = eh->eh_charset;

		break;

	default:
		/*
		subj = gen_rej_subj;
		body = gen_rej_body;
		sig = gen_rej_sig;
		incl = gen_incl;
		bincl = gen_incl_blank;
		copy_addr = bounce_email;

		break;
		*/
		/* Because of the increasing spam problem,
		   we shouldn't be sending people all this
		   mail which responds to spam sent to the
		   freedb submission address.
		*/
		cddbd_freetemp(tret);

		return EE_OK;
	}

	if(eh->eh_flags & EH_ECHO)
		echo = eh->eh_echo;
	else
		echo = 0;

	if((nfp = fopen(tret, "w+")) == NULL) {
		cddbd_log(LOG_ERR | LOG_MAIL,
		    "Can't create mail tmp file %s (%d)", tret, errno);

		return EE_ERROR;
	}

	/* Write out the note string. */
	if(eh->eh_flags & EH_NOTE) {
		if(fprintf(nfp, note, eh->eh_note) == EOF) {
			cddbd_log(LOG_ERR | LOG_MAIL,
			    "Can't write mail tmp file %s (%d)",
			    tret, errno);

			fclose(nfp);
			cddbd_freetemp(tret);

			return EE_ERROR;
		}
	}

	/* Write out the err string. */
	for(i = 0; body && body[i]; i++) {
		if(fprintf(nfp, body[i], errstr) == EOF) {
			cddbd_log(LOG_ERR | LOG_MAIL,
			    "Can't write mail tmp file %s (%d)",
			    tret, errno);

			fclose(nfp);
			cddbd_freetemp(tret);

			return EE_ERROR;
		}
	}

	rewind(fp);

	/* Write out the mail body. */
	while(fgets(buf, sizeof(buf), fp) != NULL) {
		strip_crlf(buf);

		/* remove blank lines, skip nfp write */
		if(is_blank(buf, 0))
			p = bincl;
		else
			p = incl;

		/* zeke - remove the ## comment lines, exit - we are done */
		if(is_DblHash(buf))
			break;

		if(fprintf(nfp, p, buf) == EOF) {
			cddbd_log(LOG_ERR | LOG_MAIL,
			    "Can't write mail tmp file %s (%d)", tret, errno);

			fclose(nfp);
			cddbd_freetemp(tret);

			return EE_ERROR;
		}
	}

	/*!zeke - correct comment follows ???? */
	/* Write out the err string. */
	for(i = 0; sig && sig[i]; i++) {
		if(fprintf(nfp, sig[i], admin_email) == EOF) {
			cddbd_log(LOG_ERR | LOG_MAIL,
			    "Can't write mail tmp file %s (%d)", tret, errno);

			fclose(nfp);
			cddbd_freetemp(tret);

			return EE_ERROR;
		}
	}

	fflush(nfp);

	if(fstat(fileno(nfp), &sbuf))
		len = 0;
	else
		len = sbuf.st_size;

	rewind(nfp);

	/* Figure out if we need to encode the mail. */
	if(!(flags & (MF_ENC | MF_MULTI))) {
		while(fgets(buf, sizeof(buf), nfp) != NULL) {
			if(is_rfc_1521_mappable((unsigned char *)buf, 1, 0)) {
				flags |= MF_ENC;
				break;
			}
		}
	}

	rewind(nfp);

	if(!smtp_open()) {
		fclose(nfp);
		cddbd_freetemp(tret);
		return EE_ERROR;
	}

	if(!smtp_transmit(nfp, charset, subj, eh->eh_rcpt, eh->eh_to,
			  rtn_addr, echo, flags, len, 0)) {
		fclose(nfp);
		cddbd_freetemp(tret);
		return EE_ERROR;
	}

	if(copy_addr != 0 && copy_addr[0] != '\0') {
		rewind(nfp);
		cddbd_snprintf(buf, sizeof(buf), "%s (fwd)", subj);

		if(!smtp_transmit(nfp, charset, buf, copy_addr, copy_addr,
				  rtn_addr, echo, flags, len, 0)) {
			fclose(nfp);
			cddbd_freetemp(tret);
			return EE_ERROR;
		}
	}

	smtp_close();
	fclose(nfp);
	cddbd_freetemp(tret);

	return EE_OK;
}
Ejemplo n.º 7
0
/** State machine-like implementation of an SMTP client.
 */
static void
smtp_process(void *arg, struct tcp_pcb *pcb, struct pbuf *p)
{
  struct smtp_session* s = arg;
  u16_t response_code = 0;
  u16_t tx_buf_len = 0;
  enum smtp_session_state next_state;

  if (arg == NULL) {
    /* already closed SMTP connection */
    if (p != NULL) {
      LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("Received %d bytes after closing: %s\n",
        p->tot_len, smtp_pbuf_str(p)));
      pbuf_free(p);
    }
    return;
  }

  next_state = s->state;

  if (p != NULL) {
    /* received data */
    if (s->p == NULL) {
      s->p = p;
    } else {
      pbuf_cat(s->p, p);
    }
  } else {
    /* idle timer, close connection if timed out */
    if (s->timer == 0) {
      LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("smtp_process: connection timed out, closing\n"));
      smtp_close(s, pcb, SMTP_RESULT_ERR_TIMEOUT, 0, ERR_TIMEOUT);
      return;
    }
    if (s->state == SMTP_BODY) {
      smtp_send_body(s, pcb);
      return;
    }
  }
  response_code = smtp_is_response(s);
  if (response_code) {
    LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_process: received response code: %d\n", response_code));
    if (smtp_is_response_finished(s) != ERR_OK) {
      LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_process: partly received response code: %d\n", response_code));
      /* wait for next packet to complete the respone */
      return;
    }
  } else {
    if (s->p != NULL) {
      LWIP_DEBUGF(SMTP_DEBUG_WARN, ("smtp_process: unknown data received (%s)\n",
        smtp_pbuf_str(s->p)));
      pbuf_free(s->p);
      s->p = NULL;
    }
    return;
  }

  switch(s->state)
  {
  case(SMTP_NULL):
    /* wait for 220 */
    if (response_code == 220) {
      /* then send EHLO */
      next_state = smtp_prepare_helo(s, &tx_buf_len, pcb);
    }
    break;
  case(SMTP_HELO):
    /* wait for 250 */
    if (response_code == 250) {
#if SMTP_SUPPORT_AUTH_AUTH || SMTP_SUPPORT_AUTH_LOGIN
      /* then send AUTH or MAIL */
      next_state = smtp_prepare_auth_or_mail(s, &tx_buf_len);
    }
    break;
  case(SMTP_AUTH_LOGIN):
  case(SMTP_AUTH_PLAIN):
    /* wait for 235 */
    if (response_code == 235) {
#endif /* SMTP_SUPPORT_AUTH_AUTH || SMTP_SUPPORT_AUTH_LOGIN */
      /* send MAIL */
      next_state = smtp_prepare_mail(s, &tx_buf_len);
    }
    break;
#if SMTP_SUPPORT_AUTH_LOGIN
  case(SMTP_AUTH_LOGIN_UNAME):
    /* wait for 334 Username */
    if (response_code == 334) {
      if (pbuf_strstr(s->p, SMTP_RESP_LOGIN_UNAME) != 0xFFFF) {
        /* send username */
        next_state = smtp_prepare_auth_login_uname(s, &tx_buf_len);
      }
    }
    break;
  case(SMTP_AUTH_LOGIN_PASS):
    /* wait for 334 Password */
    if (response_code == 334) {
      if (pbuf_strstr(s->p, SMTP_RESP_LOGIN_PASS) != 0xFFFF) {
        /* send username */
        next_state = smtp_prepare_auth_login_pass(s, &tx_buf_len);
      }
    }
    break;
#endif /* SMTP_SUPPORT_AUTH_LOGIN */
  case(SMTP_MAIL):
    /* wait for 250 */
    if (response_code == 250) {
      /* send RCPT */
      next_state = smtp_prepare_rcpt(s, &tx_buf_len);
    }
    break;
  case(SMTP_RCPT):
    /* wait for 250 */
    if (response_code == 250) {
      /* send DATA */
      SMEMCPY(s->tx_buf, SMTP_CMD_DATA, SMTP_CMD_DATA_LEN);
      tx_buf_len = SMTP_CMD_DATA_LEN;
      next_state = SMTP_DATA;
    }
    break;
  case(SMTP_DATA):
    /* wait for 354 */
    if (response_code == 354) {
      /* send email header */
      next_state = smtp_prepare_header(s, &tx_buf_len);
    }
    break;
  case(SMTP_BODY):
    /* nothing to be done here, handled somewhere else */
    break;
  case(SMTP_QUIT):
    /* wait for 250 */
    if (response_code == 250) {
      /* send QUIT */
      next_state = smtp_prepare_quit(s, &tx_buf_len);
    }
    break;
  case(SMTP_CLOSED):
    /* nothing to do, wait for connection closed from server */
    return;
  default:
    LWIP_DEBUGF(SMTP_DEBUG_SERIOUS, ("Invalid state: %d/%s\n", (int)s->state,
      smtp_state_str[s->state]));
    break;
  }
  if (s->state == next_state) {
    LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("smtp_process[%s]: unexpected response_code, closing: %d (%s)\n",
      smtp_state_str[s->state], response_code, smtp_pbuf_str(s->p)));
    /* close connection */
    smtp_close(s, pcb, SMTP_RESULT_ERR_SVR_RESP, response_code, ERR_OK);
    return;
  }
  if (tx_buf_len > 0) {
    SMTP_TX_BUF_MAX(tx_buf_len);
    if (tcp_write(pcb, s->tx_buf, tx_buf_len, TCP_WRITE_FLAG_COPY) == ERR_OK) {
      LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_process[%s]: received command %d (%s)\n",
        smtp_state_str[s->state], response_code, smtp_pbuf_str(s->p)));
      LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_process[%s]: sent %"U16_F" bytes: \"%s\"\n",
        smtp_state_str[s->state], tx_buf_len, s->tx_buf));
      s->timer = SMTP_TIMEOUT;
      pbuf_free(s->p);
      s->p = NULL;
      LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_process: changing state from %s to %s\n",
        smtp_state_str[s->state], smtp_state_str[next_state]));
      s->state = next_state;
      if (next_state == SMTP_BODY) {
        /* try to stream-send body data right now */
        smtp_send_body(s, pcb);
      } else if (next_state == SMTP_CLOSED) {
        /* sent out all data, delete structure */
        tcp_arg(pcb, NULL);
        smtp_free(s, SMTP_RESULT_OK, 0, ERR_OK);
      }
    }
  }
}
Ejemplo n.º 8
0
SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service,
			    unsigned long port,long options)
{
  SENDSTREAM *stream = NIL;
  long reply;
  char *s,tmp[MAILTMPLEN];
  NETSTREAM *netstream;
  NETMBX mb;
  if (!(hostlist && *hostlist)) mm_log ("Missing SMTP service host",ERROR);
				/* maximum domain name is 64 characters */
  else do if (strlen (*hostlist) < SMTPMAXDOMAIN) {
    sprintf (tmp,"{%.1000s}",*hostlist);
    if (!mail_valid_net_parse_work (tmp,&mb,service ? service : "smtp") ||
	mb.anoflag || mb.readonlyflag) {
      sprintf (tmp,"Invalid host specifier: %.80s",*hostlist);
      mm_log (tmp,ERROR);
    }
    else {			/* light tryssl flag if requested */
      mb.trysslflag = (options & SOP_TRYSSL) ? T : NIL;
				/* explicit port overrides all */
      if (mb.port) port = mb.port;
				/* else /submit overrides port argument */
      else if (!compare_cstring (mb.service,"submit")) {
	port = SUBMITTCPPORT;	/* override port, use IANA name */
	strcpy (mb.service,"submission");
      }
				/* else port argument overrides SMTP port */
      else if (!port) port = smtp_port ? smtp_port : SMTPTCPPORT;
      if (netstream =		/* try to open ordinary connection */
	  net_open (&mb,dv,port,
		    (NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL),
		    "*smtps",smtp_sslport ? smtp_sslport : SMTPSSLPORT)) {
	stream = (SENDSTREAM *) memset (fs_get (sizeof (SENDSTREAM)),0,
					sizeof (SENDSTREAM));
	stream->netstream = netstream;
	stream->host = cpystr ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL) ?
			       net_host (netstream) : mb.host);
	stream->debug = (mb.dbgflag || (options & OP_DEBUG)) ? T : NIL;
	if (options & SOP_SECURE) mb.secflag = T;
				/* get name of local host to use */
	s = compare_cstring ("localhost",mb.host) ?
	  net_localhost (netstream) : "localhost";

	do reply = smtp_reply (stream);
	while ((reply < 100) || (stream->reply[3] == '-'));
	if (reply != SMTPGREET){/* get SMTP greeting */
	  sprintf (tmp,"SMTP greeting failure: %.80s",stream->reply);
	  mm_log (tmp,ERROR);
	  stream = smtp_close (stream);
	}
				/* try EHLO first, then HELO */
	else if (((reply = smtp_ehlo (stream,s,&mb)) != SMTPOK) &&
		 ((reply = smtp_send (stream,"HELO",s)) != SMTPOK)) {
	  sprintf (tmp,"SMTP hello failure: %.80s",stream->reply);
	  mm_log (tmp,ERROR);
	  stream = smtp_close (stream);
	}
	else {
	  NETDRIVER *ssld =(NETDRIVER *)mail_parameters(NIL,GET_SSLDRIVER,NIL);
	  sslstart_t stls = (sslstart_t) mail_parameters(NIL,GET_SSLSTART,NIL);
	  ESMTP.ok = T;		/* ESMTP server, start TLS if present */
	  if (!dv && stls && ESMTP.service.starttls &&
	      !mb.sslflag && !mb.notlsflag &&
	      (smtp_send (stream,"STARTTLS",NIL) == SMTPGREET)) {
	    mb.tlsflag = T;	/* TLS OK, get into TLS at this end */
	    stream->netstream->dtb = ssld;
				/* TLS started, negotiate it */
	    if (!(stream->netstream->stream = (*stls)
		  (stream->netstream->stream,mb.host,
		   (mb.tlssslv23 ? NIL : NET_TLSCLIENT) |
		   (mb.novalidate ? NET_NOVALIDATECERT:NIL)))){
				/* TLS negotiation failed after STARTTLS */
	      sprintf (tmp,"Unable to negotiate TLS with this server: %.80s",
		       mb.host);
	      mm_log (tmp,ERROR);
				/* close without doing QUIT */
	      if (stream->netstream) net_close (stream->netstream);
	      stream->netstream = NIL;
	      stream = smtp_close (stream);
	    }
				/* TLS OK, re-negotiate EHLO */
	    else if ((reply = smtp_ehlo (stream,s,&mb)) != SMTPOK) {
	      sprintf (tmp,"SMTP EHLO failure after STARTTLS: %.80s",
		       stream->reply);
	      mm_log (tmp,ERROR);
	      stream = smtp_close (stream);
	    }
	    else ESMTP.ok = T;	/* TLS OK and EHLO successful */
	  }
	  else if (mb.tlsflag) {/* user specified /tls but can't do it */
	    sprintf (tmp,"TLS unavailable with this server: %.80s",mb.host);
	    mm_log (tmp,ERROR);
	    stream = smtp_close (stream);
	  }

				/* remote name for authentication */
	  if (stream && ((mb.secflag || mb.user[0]))) {
	    if (ESMTP.auth) {	/* use authenticator? */
	      if ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL)) {
				/* remote name for authentication */
		strncpy (mb.host,
			 (long) mail_parameters (NIL,GET_SASLUSESPTRNAME,NIL) ?
			 net_remotehost (netstream) : net_host (netstream),
			 NETMAXHOST-1);
		mb.host[NETMAXHOST-1] = '\0';
	      }
	      if (!smtp_auth (stream,&mb,tmp)) stream = smtp_close (stream);
	    }
	    else {		/* no available authenticators? */
	      sprintf (tmp,"%sSMTP authentication not available: %.80s",
		       mb.secflag ? "Secure " : "",mb.host);
	      mm_log (tmp,ERROR);
	      stream = smtp_close (stream);
	    }
	  }
	}
      }
    }
  } while (!stream && *++hostlist);
  if (stream) {			/* set stream options if have a stream */
    if (options &(SOP_DSN | SOP_DSN_NOTIFY_FAILURE | SOP_DSN_NOTIFY_DELAY |
		  SOP_DSN_NOTIFY_SUCCESS | SOP_DSN_RETURN_FULL)) {
      ESMTP.dsn.want = T;
      if (options & SOP_DSN_NOTIFY_FAILURE) ESMTP.dsn.notify.failure = T;
      if (options & SOP_DSN_NOTIFY_DELAY) ESMTP.dsn.notify.delay = T;
      if (options & SOP_DSN_NOTIFY_SUCCESS) ESMTP.dsn.notify.success = T;
      if (options & SOP_DSN_RETURN_FULL) ESMTP.dsn.full = T;
    }
    if (options & SOP_8BITMIME) ESMTP.eightbit.want = T;
  }
  return stream;
}