bool smtp_client::rcpt_to(const char* to) { if (to == NULL || *to == 0) { logger_error("to null"); return false; } return smtp_rcpt(client_, to) == 0 ? true : false; }
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; }
long smtp_mail (SENDSTREAM *stream,char *type,ENVELOPE *env,BODY *body) { RFC822BUFFER buf; char tmp[SENDBUFLEN+1]; long error = NIL; long retry = NIL; buf.f = smtp_soutr; /* initialize buffer */ buf.s = stream->netstream; buf.end = (buf.beg = buf.cur = tmp) + SENDBUFLEN; tmp[SENDBUFLEN] = '\0'; /* must have additional null guard byte */ if (!(env->to || env->cc || env->bcc)) { /* no recipients in request */ smtp_seterror (stream,SMTPHARDERROR,"No recipients specified"); return NIL; } do { /* make sure stream is in good shape */ if (retry) { /* need to retry with authentication? */ NETMBX mb; /* yes, build remote name for authentication */ sprintf (tmp,"{%.200s/smtp%s}<none>", (long) mail_parameters (NIL,GET_TRUSTDNS,NIL) ? ((long) mail_parameters (NIL,GET_SASLUSESPTRNAME,NIL) ? net_remotehost (stream->netstream) : net_host (stream->netstream)) : stream->host, (stream->netstream->dtb == (NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL)) ? "/ssl" : ""); mail_valid_net_parse (tmp,&mb); smtp_send (stream,"RSET",NIL); if (!smtp_auth (stream,&mb,tmp)) return NIL; retry = NIL; /* no retry at this point */ } strcpy (tmp,"FROM:<"); /* compose "MAIL FROM:<return-path>" */ #ifdef RFC2821 if (env->return_path && env->return_path->host && !((strlen (env->return_path->mailbox) > SMTPMAXLOCALPART) || (strlen (env->return_path->host) > SMTPMAXDOMAIN))) { rfc822_cat (tmp,env->return_path->mailbox,NIL); sprintf (tmp + strlen (tmp),"@%s",env->return_path->host); } #else /* old code with A-D-L support */ if (env->return_path && env->return_path->host && !((env->return_path->adl && (strlen (env->return_path->adl) > SMTPMAXPATH)) || (strlen (env->return_path->mailbox) > SMTPMAXLOCALPART) || (strlen (env->return_path->host) > SMTPMAXDOMAIN))) rfc822_address (tmp,env->return_path); #endif strcat (tmp,">"); if (ESMTP.ok) { if (ESMTP.eightbit.ok && ESMTP.eightbit.want) strcat (tmp," BODY=8BITMIME"); if (ESMTP.dsn.ok && ESMTP.dsn.want) { strcat (tmp,ESMTP.dsn.full ? " RET=FULL" : " RET=HDRS"); if (ESMTP.dsn.envid) sprintf (tmp + strlen (tmp)," ENVID=%.100s",ESMTP.dsn.envid); } } /* send "MAIL FROM" command */ switch (smtp_send (stream,type,tmp)) { case SMTPUNAVAIL: /* mailbox unavailable? */ case SMTPWANTAUTH: /* wants authentication? */ case SMTPWANTAUTH2: if (ESMTP.auth) retry = T;/* yes, retry with authentication */ case SMTPOK: /* looks good */ break; default: /* other failure */ smtp_send (stream,"RSET",NIL); return NIL; } /* negotiate the recipients */ if (!retry && env->to) retry = smtp_rcpt (stream,env->to,&error); if (!retry && env->cc) retry = smtp_rcpt (stream,env->cc,&error); if (!retry && env->bcc) retry = smtp_rcpt (stream,env->bcc,&error); if (!retry && error) { /* any recipients failed? */ smtp_send (stream,"RSET",NIL); smtp_seterror (stream,SMTPHARDERROR,"One or more recipients failed"); return NIL; } } while (retry); /* negotiate data command */ if (!(smtp_send (stream,"DATA",NIL) == SMTPREADY)) { smtp_send (stream,"RSET",NIL); return NIL; } /* send message data */ if (!rfc822_output_full (&buf,env,body, ESMTP.eightbit.ok && ESMTP.eightbit.want)) { smtp_fake (stream,"SMTP connection broken (message data)"); return NIL; /* can't do much else here */ } /* send trailing dot */ if (smtp_send (stream,".",NIL) != SMTPOK) { smtp_send (stream,"RSET",NIL); return NIL; } return LONGT; }
static gboolean smtp_transport_send_to_sync (CamelTransport *transport, CamelMimeMessage *message, CamelAddress *from, CamelAddress *recipients, gboolean *out_sent_message_saved, GCancellable *cancellable, GError **error) { CamelSmtpTransport *smtp_transport = CAMEL_SMTP_TRANSPORT (transport); CamelInternetAddress *cia; gboolean has_8bit_parts; const gchar *addr; gint i, len; smtp_debug_print_server_name (CAMEL_SERVICE (transport), "Sending with"); if (!smtp_transport->connected) { g_set_error ( error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_NOT_CONNECTED, _("Cannot send message: service not connected.")); return FALSE; } if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (from), 0, NULL, &addr)) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot send message: sender address not valid.")); return FALSE; } camel_operation_push_message (cancellable, _("Sending message")); /* find out if the message has 8bit mime parts */ has_8bit_parts = camel_mime_message_has_8bit_parts (message); /* If the connection needs a ReSET, then do so */ if (smtp_transport->need_rset && !smtp_rset (smtp_transport, cancellable, error)) { camel_operation_pop_message (cancellable); return FALSE; } smtp_transport->need_rset = FALSE; /* rfc1652 (8BITMIME) requires that you notify the ESMTP daemon that * you'll be sending an 8bit mime message at "MAIL FROM:" time. */ if (!smtp_mail ( smtp_transport, addr, has_8bit_parts, cancellable, error)) { camel_operation_pop_message (cancellable); return FALSE; } len = camel_address_length (recipients); if (len == 0) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot send message: no recipients defined.")); camel_operation_pop_message (cancellable); smtp_transport->need_rset = TRUE; return FALSE; } cia = CAMEL_INTERNET_ADDRESS (recipients); for (i = 0; i < len; i++) { gchar *enc; if (!camel_internet_address_get (cia, i, NULL, &addr)) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot send message: " "one or more invalid recipients")); camel_operation_pop_message (cancellable); smtp_transport->need_rset = TRUE; return FALSE; } enc = camel_internet_address_encode_address (NULL, NULL, addr); if (!smtp_rcpt (smtp_transport, enc, cancellable, error)) { g_free (enc); camel_operation_pop_message (cancellable); smtp_transport->need_rset = TRUE; return FALSE; } g_free (enc); } if (!smtp_data (smtp_transport, message, cancellable, error)) { camel_operation_pop_message (cancellable); smtp_transport->need_rset = TRUE; return FALSE; } camel_operation_pop_message (cancellable); return TRUE; }