int smtp_greet(SMTP_CLIENT *client, const char* name, int ehlo) { if (ehlo) return smtp_ehlo(client, name); else return smtp_helo(client, name); }
/* Called by: */ int smtp_decode_req(struct hi_thr* hit, struct hi_io* io) { struct hi_pdu* req = io->cur_pdu; D("smtp_state(%d) scan(%.*s)", io->ad.smtp.state, (int)MIN(7, req->ap - req->scan), req->scan); switch (io->ad.smtp.state) { case SMTP_START: return smtp_ehlo(hit, io, req); case SMTP_MAIN: return smtp_mail_from(hit, io, req); case SMTP_TO: return smtp_rcpt_to(hit, io, req); case SMTP_MORE0: case SMTP_MORE1: case SMTP_MORE2: return smtp_data(hit, io, req); case SMTP_WAIT: case SMTP_STATUS: D("Unexpected state %x", io->ad.smtp.state); case SMTP_END: return smtp_mail_from(hit, io, req); default: NEVERNEVER("impossible SMTP state %d", io->ad.smtp.state); } return 0; }
static gint smtp_session_recv_msg(Session *session, const gchar *msg) { SMTPSession *smtp_session = SMTP_SESSION(session); gboolean cont = FALSE; if (strlen(msg) < 4) { log_warning(_("bad SMTP response\n")); return -1; } switch (smtp_session->state) { case SMTP_EHLO: case SMTP_STARTTLS: case SMTP_AUTH: case SMTP_AUTH_PLAIN: case SMTP_AUTH_LOGIN_USER: case SMTP_AUTH_LOGIN_PASS: case SMTP_AUTH_CRAM_MD5: log_print("ESMTP< %s\n", msg); break; default: log_print("SMTP< %s\n", msg); break; } if (msg[0] == '5' && msg[1] == '0' && (msg[2] == '4' || msg[2] == '3' || msg[2] == '1')) { log_warning(_("error occurred on SMTP session\n")); smtp_session->state = SMTP_ERROR; smtp_session->error_val = SM_ERROR; g_free(smtp_session->error_msg); smtp_session->error_msg = g_strdup(msg); return -1; } if (!strncmp(msg, "535", 3)) { log_warning(_("error occurred on authentication\n")); smtp_session->state = SMTP_ERROR; smtp_session->error_val = SM_AUTHFAIL; g_free(smtp_session->error_msg); smtp_session->error_msg = g_strdup(msg); return -1; } if (msg[0] != '1' && msg[0] != '2' && msg[0] != '3') { log_warning(_("error occurred on SMTP session\n")); smtp_session->state = SMTP_ERROR; smtp_session->error_val = SM_ERROR; g_free(smtp_session->error_msg); smtp_session->error_msg = g_strdup(msg); return -1; } if (msg[3] == '-') cont = TRUE; else if (msg[3] != ' ' && msg[3] != '\0') { log_warning(_("bad SMTP response\n")); smtp_session->state = SMTP_ERROR; smtp_session->error_val = SM_UNRECOVERABLE; return -1; } /* ignore all multiline responses except for EHLO */ if (cont && smtp_session->state != SMTP_EHLO) return session_recv_msg(session); switch (smtp_session->state) { case SMTP_READY: if (strstr(msg, "ESMTP")) smtp_session->is_esmtp = TRUE; case SMTP_CONNECTED: #if USE_OPENSSL if (smtp_session->user || session->ssl_type != SSL_NONE || smtp_session->is_esmtp) #else if (smtp_session->user || smtp_session->is_esmtp) #endif smtp_ehlo(smtp_session); else smtp_helo(smtp_session); break; case SMTP_HELO: smtp_from(smtp_session); break; case SMTP_EHLO: smtp_ehlo_recv(smtp_session, msg); if (cont == TRUE) break; if (smtp_session->max_message_size > 0 && smtp_session->max_message_size < smtp_session->send_data_len) { log_warning(_("Message is too big " "(Maximum size is %s)\n"), to_human_readable( (off_t)(smtp_session->max_message_size))); smtp_session->state = SMTP_ERROR; smtp_session->error_val = SM_ERROR; return -1; } #if USE_OPENSSL if (session->ssl_type == SSL_STARTTLS && smtp_session->tls_init_done == FALSE) { smtp_starttls(smtp_session); break; } #endif if (smtp_session->user) { if (smtp_auth(smtp_session) != SM_OK) smtp_from(smtp_session); } else smtp_from(smtp_session); break; case SMTP_STARTTLS: #if USE_OPENSSL if (session_start_tls(session) < 0) { log_warning(_("can't start TLS session\n")); smtp_session->state = SMTP_ERROR; smtp_session->error_val = SM_ERROR; return -1; } smtp_session->tls_init_done = TRUE; smtp_ehlo(smtp_session); #endif break; case SMTP_AUTH: smtp_auth_recv(smtp_session, msg); break; case SMTP_AUTH_LOGIN_USER: smtp_auth_login_user_recv(smtp_session, msg); break; case SMTP_AUTH_PLAIN: case SMTP_AUTH_LOGIN_PASS: case SMTP_AUTH_CRAM_MD5: smtp_from(smtp_session); break; case SMTP_FROM: if (smtp_session->cur_to) smtp_rcpt(smtp_session); break; case SMTP_RCPT: if (smtp_session->cur_to) smtp_rcpt(smtp_session); else smtp_data(smtp_session); break; case SMTP_DATA: smtp_send_data(smtp_session); break; case SMTP_EOM: smtp_quit(smtp_session); break; case SMTP_QUIT: session_disconnect(session); break; case SMTP_ERROR: default: log_warning(_("error occurred on SMTP session\n")); smtp_session->error_val = SM_ERROR; return -1; } if (cont) return session_recv_msg(session); return 0; }
/*Attempt to send a message*/ void SMTP_SendThread( void * dummy ) { int l_nReturn; SMTP_lock(); /*Connect to the SMTP server.*/ l_nReturn = smtp_connect( g_pClient, g_szServer, 25 ); if ( l_nReturn != NSMAIL_OK ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } l_nReturn = smtp_processResponses( g_pClient ); if ( l_nReturn != NSMAIL_OK || g_serverError == TRUE ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } /*Send the EHLO command passing in the domain name.*/ l_nReturn = smtp_ehlo( g_pClient, g_szDomain ); if ( l_nReturn != NSMAIL_OK ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } l_nReturn = smtp_processResponses( g_pClient ); if ( l_nReturn != NSMAIL_OK || g_serverError == TRUE ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } /*Send the MAIL FROM command.*/ l_nReturn = smtp_mailFrom( g_pClient, g_szSender, NULL ); if ( l_nReturn != NSMAIL_OK ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } l_nReturn = smtp_processResponses( g_pClient ); if ( l_nReturn != NSMAIL_OK || g_serverError == TRUE ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } /*Send the RCPT TO command.*/ l_nReturn = smtp_rcptTo( g_pClient, g_szRecipient, NULL ); if ( l_nReturn != NSMAIL_OK ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } l_nReturn = smtp_processResponses( g_pClient ); if ( l_nReturn != NSMAIL_OK || g_serverError == TRUE ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } /*Send the DATA command.*/ l_nReturn = smtp_data( g_pClient ); if ( l_nReturn != NSMAIL_OK ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } l_nReturn = smtp_processResponses( g_pClient ); if ( l_nReturn != NSMAIL_OK || g_serverError == TRUE ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } /* Send the message.*/ l_nReturn = smtp_send( g_pClient, g_szData ); if ( l_nReturn != NSMAIL_OK ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } l_nReturn = smtp_processResponses( g_pClient ); if ( l_nReturn != NSMAIL_OK || g_serverError == TRUE ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } l_nReturn = smtp_quit( g_pClient ); if ( l_nReturn != NSMAIL_OK ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } l_nReturn = smtp_processResponses( g_pClient ); if ( l_nReturn != NSMAIL_OK || g_serverError == TRUE ) { printf( "smtptest.c::SMTP_SendThread" ); SMTP_unlock(); return; } SMTP_unlock(); }
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; }