Exemple #1
0
/* greeting can be multi line */
static int read_greetings(void)
{
    int
        lcnt=0,
        rc=(-1);

    rc=read_smtp_line();
    if (rc < 0)
        goto cleanup;

    s_esmtp=g_esmtp; /* if forced with -ehlo */

    if (smtp_code != 220)
    {
        read_smtp_multi_lines();
        errorMsg("Expected smtp code 220, got %d\n",smtp_code);
        rc=(-1);
        goto cleanup;
    }
    if (mutilsStristr(smtp_line,"ESMTP"))
    {
        s_esmtp=1;
    }
    /* greeting can be multi-line */
    if (smtp_sep == A_DASH)
    {
        for (;;)
        {
            rc=read_smtp_line();
            if (rc < 0)
                break;
            lcnt++;
            if (lcnt >= 100)
            {
                errorMsg("Too many greeting lines\n");
                rc=(-1);
                goto cleanup;
            }
            if (mutilsStristr(smtp_line,"ESMTP"))
            {
                s_esmtp=1;
            }
            if (smtp_sep != A_DASH)
                break;
        }
    }
cleanup:
    smtp_sep = A_SPACE;
    return(rc);
}
Exemple #2
0
int read_smtp_multi_lines(void)
{
    int
        rc,
        lcnt = 0;
    if (smtp_sep == A_DASH)
    {
        for (;;)
        {
            rc=read_smtp_line();
            if (rc < 0)
                break;
            lcnt++;
            if (lcnt >= 100)
            {
                errorMsg("Too many lines from server\n");
                rc=(-1);
                goto ExitProcessing;
            }
            if (smtp_sep != A_DASH)
                break;
        }
    }
    smtp_sep = A_SPACE;
    return(0);
ExitProcessing:
    return(1);
}
Exemple #3
0
/* SMTP: RCPT TO */
static int smtp_RCPT_TO(void)
{
    Sll
        *l,
        *al;

    Address
        *a;

    char
        *x;

    int
        rc;

    al=getAddressList();
    
    for (l=al; l; l=l->next)
    {
        a=(Address *) l->data;
        if (! a)
            return(-1);
        if (! a->address)
            return(-1);

        memset(buf,0,sizeof(buf));
        x=getenv("NOTIFY_RCPT");
        if (x != NULL)
        {
            /* MS Exchange has it */
            showVerbose("NOTIFY_RCPT=%s\n",x);
            (void) snprintf(buf,sizeof(buf)-1,"RCPT TO: %s %s\r\n",
                            a->address,x);
        }
        else
        {
            (void) snprintf(buf,sizeof(buf)-1,"RCPT TO: <%s>\r\n",a->address);
        }

        showVerbose("[C] %s",buf);
        
        msock_puts(buf);
        rc=read_smtp_line();
        if (rc == 0)
        {
            if (smtp_code != 250)
            {
                errorMsg("RCPT TO: <%s> failed '%d:%s'\n",
                        a->address,smtp_code,smtp_line);
                smtp_RSET();
                return(-1);
            }
        }
    }
    return (0);

}
Exemple #4
0
/* SMTP: quit */
static int smtp_QUIT(void)
{
    showVerbose("[C] QUIT\r\n");
    msock_puts("QUIT\r\n");
    read_smtp_line();
    /*
    ** google does not seem to write anything back in response to QUIT
    ** command. I'll ignore it anyway
    */
    return(0);
}
Exemple #5
0
int smtp_start_tls(int sfd)
{
    int
        rc=(-1);
#ifdef HAVE_OPENSSL
    SSL
        *ssl=NULL;
#endif /* HAVE_OPENSSL */
    memset(buf,0,sizeof(buf));
    (void) snprintf(buf,sizeof(buf)-1,"%s\r\n","STARTTLS");
    showVerbose("[C] %s",buf);
    msock_puts(buf);
    rc=read_smtp_line();
    if (smtp_code != 220)
    {
        errorMsg("Unknown STARTTLS response code %d\n",smtp_code);
        return(-1);
    }
#ifdef HAVE_OPENSSL
    ssl=msock_get_ssl();
    if (ssl)
    {
        if (!SSL_set_fd(ssl,sfd))
        {
            errorMsg("failed to set socket to SSL\n");
            return(-1);
        }
        /* must set back to msock's static */
        msock_set_ssl(ssl);
        rc=SSL_connect(ssl);
        if (rc < 1)
        {
            errorMsg("SSL connection failed\n");
            ERR_print_errors_fp(stderr);
            return(-1);
        }
        print_cert_info(ssl);
        /* tell msock everything is ssl after that */
        msock_turn_ssl_on();
        rc=0;
    }
    else
    {
        errorMsg("Could not start STARTTLS, SSL not initialized properly");
        rc=(-1);
    }
#else
    errorMsg("Not Compiled with OpenSSL, will not try STARTTLS");
    rc=(-1);
#endif /*HAVE_OPENSSL */
    return(rc);
}
Exemple #6
0
/* SMTP: HELO */
static int say_helo(char *helo_domain)
{
    int
        cnt=0,
        rc;

    (void) snprintf(buf,sizeof(buf)-1,"%s %s\r\n",
                    s_esmtp ? "EHLO" : "HELO",helo_domain);
    showVerbose("[C] %s",buf);

    /* send */
    msock_puts(buf);
    rc=read_smtp_line();
    if (smtp_code != 250)
    {
        errorMsg("%s failed", s_esmtp ? "EHLO" : "HELO");
        return(-1);
    }
    /* read all the capabilities if separator is - */
    if (smtp_sep == A_DASH)
    {
        for (;;)
        {
            rc=read_smtp_line();
            if (rc == 0)
                add_server_cap_to_list(smtp_line);
            cnt++;
            if (cnt >= 1000)
                break;
            if (rc < 0 || smtp_sep != A_DASH)
                break;
        }
    }
    smtp_sep = A_SPACE;

    return(rc);
}
Exemple #7
0
/* SMTP: MAIL FROM */
static int smtp_MAIL_FROM(char *from)
{
    memset(buf,0,sizeof(buf));
    (void) snprintf(buf,sizeof(buf)-1,"MAIL FROM: <%s>\r\n",from);
    showVerbose("[C] %s",buf);

    msock_puts(buf);
    read_smtp_line();
    if (smtp_code != 250)
    {
        errorMsg("MAIL FROM failed: '%d %s'",smtp_code,smtp_line);
        return(-1);
    }
    return(0);
}
Exemple #8
0
/* SMTP: DATA */
static int smtp_DATA(void)
{
    int
        rc;

    msock_puts("DATA\r\n");
    showVerbose("[C] DATA\r\n");

    rc=read_smtp_line();
    if (rc == 0)
    {
        if (smtp_code != 354)
        {
            errorMsg("DATA failed: '%d %s'\n",smtp_code,smtp_line);
            return(-1);
        }
    }
    return(0);
}
Exemple #9
0
/* return 0 on success, -1 on failure */
int smtpEom(int sfd)
{
    int
        rc;

    msock_puts("\r\n.\r\n");

    showVerbose("\r\n[C] .\r\n");

    /*
    ** Bug# 1 
    ** we want to see smtp code 250 now
    ** if mail is too big, it can mail with 552 message too large
    */
    rc = read_smtp_line();
    if (smtp_code != 250)
    {
        errorMsg("Expected smtp code 250, got %d\n",smtp_code);
        rc = (-1);
    }

    return(rc);
}
Exemple #10
0
/* aborts current mail transaction and cause both ends to reset */
static int smtp_RSET()
{
    msock_puts("RSET\r\n");
    return(read_smtp_line());
}
Exemple #11
0
/* returns 0 on success, -1 on failure */
int send_the_mail(char *from,char *to,char *cc,char *bcc,char *sub,
             char *smtp_server,int smtp_port,char *helo_domain,
             char *attach_file,char *txt_msg_file,char *the_msg,int is_mime,char *rrr,char *rt,
             int add_dateh)
{
    SOCKET
        sfd;

    TheMail
        *mail;


    Sll
        *al;

    int
        rc=(-1);

    char
        *mech=NULL,
        *auth=NULL;

    /*
    unsigned char
		*b64=NULL;
    */
    char
        *b64 = NULL;

    int
        authenticated=0;
 
    /*
    (void) fprintf(stderr,"From: %s\n",from);
    (void) fprintf(stderr,"To: %s\n",to);
    (void) fprintf(stderr,"Cc: %s\n",cc);
    (void) fprintf(stderr,"Cc: %s\n",bcc);
    (void) fprintf(stderr,"Sub: %s\n",sub);
    (void) fprintf(stderr,"smtp: %s\n",smtp_server);
    (void) fprintf(stderr,"smtp port: %d\n",smtp_port);
    (void) fprintf(stderr,"domain: %s\n",helo_domain);
    (void) fprintf(stderr,"attach file: %s\n",attach_file);
    (void) fprintf(stderr,"txt_msg_file: %s\n",txt_msg_file);
    (void) fprintf(stderr,"the_msg: %s\n",the_msg);
    (void) fprintf(stderr,"is_mime: %d\n",is_mime);
    */

    al=getAddressList();

    if (al == (Sll *) NULL)
    {
        errorMsg("No To address/es specified");
        return (-1);
    }

    if (from == (char *) NULL)
    {
        errorMsg("No From address specified");
        return (-1);
    }

    if (smtp_server == (char *) NULL)
        smtp_server="127.0.0.1";

    if (smtp_port == -1)
        smtp_port=MAILSEND_SMTP_PORT;

    if (sub == (char *) NULL)
        sub=MAILSEND_DEF_SUB;

    if (helo_domain == (char *) NULL)
    {
        errorMsg("No domain specified");
        return (-1);
    }

    mail=newTheMail();
    if (mail == (TheMail *) NULL)
    {
        errorMsg("Error: malloc failed in createTheMail()\n");
        return (-1);
    }

    showVerbose("Connecting to %s:%d\n",smtp_server,smtp_port);
    /* open the network connection */
    sfd=smtpConnect(smtp_server,smtp_port);
    if (sfd == INVALID_SOCKET)
    {
        rc=(-1);
        goto cleanup;
    }

    if (g_do_ssl) /* smtp.gmail:465 supports it for example */
    {
        turn_on_raw_ssl(sfd);
    }

    /* read greeting */
    rc=read_greetings();
    if (rc < 0)
        goto cleanup;

    /* say HELO/EHLO */
    say_helo(helo_domain);

    /* check if the server supports STARTTLS or TLS */
    if (g_do_starttls)
    {
        if (check_server_cap("STARTTLS") ||
            check_server_cap("TLS"))
        {
            rc=smtp_start_tls(sfd);
            if (rc == 0)
            {
               /* send HELO again */
                say_helo(helo_domain);
            }
        }
    }

    if (g_do_auth || g_auth_cram_md5 || g_auth_login || g_auth_plain)
    {
        auth=check_server_cap("AUTH");
    }
    if (!auth)
        goto MailFrom;
    /*
    (void) fprintf(stderr,"auth=%s\n",auth);
    (void) fprintf(stderr," g_auth_cram_md5=%d; g_auth_login=%d; g_auth_plain=%d\n", g_auth_cram_md5, g_auth_login, g_auth_plain);
    */

    /*
    if (auth && g_do_auth)
    {
        g_auth_cram_md5=1;
        g_auth_login=1;
        g_auth_plain=1;
    }
    */
    /* Try CRAM-MD5 first */
    mech="CRAM-MD5";
    if (g_auth_cram_md5 && check_server_cap(mech))
    {
        char
            *cmd5 = NULL;

        CHECK_USERNAME(mech);
        CHECK_USERPASS(mech);

#ifndef HAVE_OPENSSL
        errorMsg("Must be compiled with OpenSSL in order to get CRAM-MD5 support\n");
        goto cleanup;
#endif /* !HAVE_OPENSSL */
        showVerbose("Using AUTH %s\n",mech);
        memset(buf,0,sizeof(buf));
        (void) snprintf(buf,sizeof(buf)-1,"AUTH %s\r\n",mech);
        showVerbose("[C] %s",buf);
        msock_puts(buf);

        read_smtp_line();
        if (smtp_code != 334)
        {
            errorMsg("AUTH CRAM-MD5 failed: '%d %s'",
                    smtp_code,
                    smtp_line);
            rc=(-1);
            goto cleanup;
        }
        cmd5 = encode_cram_md5(smtp_line,g_username,g_userpass);
        if (cmd5 == NULL)
        {
            errorMsg("Could not encode CRAM-MD5");
            rc = (-1);
            goto cleanup;
        }
        memset(buf,0,sizeof(buf));
        (void) snprintf(buf,sizeof(buf)-1,"%s\r\n",cmd5);
        showVerbose("[C] %s",buf);
        msock_puts(buf);
        read_smtp_line();
        if (smtp_code != 235)
        {
            errorMsg("AUTH CRAM-MD5 failed: '%d %s'",
                    smtp_code,
                    smtp_line);
            rc=(-1);
            goto cleanup;
        }

        showVerbose("%s Authentication succeeded\n",mech);
        authenticated++;
        if (cmd5)
        {
            (void) free((char *) cmd5);
        }
    }
    else
    {
        if (g_auth_cram_md5)
            showVerbose("Server does not support AUTH CRAM-MD5\n");
    }
    if (authenticated)
        goto MailFrom;

    mech="LOGIN";
    if (g_auth_login && check_server_cap(mech))
    {
        CHECK_USERNAME(mech);
        CHECK_USERPASS(mech);

        showVerbose("Using AUTH %s\n",mech);
        memset(buf,0,sizeof(buf));
        (void) snprintf(buf,sizeof(buf)-1,"AUTH %s\r\n",mech);
        showVerbose("[C] %s",buf);
        msock_puts(buf);

        read_smtp_line();
        if (smtp_code != 334)
        {
            errorMsg("AUTH LOGIN failed: '%d %s'",
                    smtp_code,
                    smtp_line);
            rc=(-1);
            goto cleanup;
        }
        /*
        b64=mutils_encode_base64(g_username,strlen(g_username),&b64len);
        b64[b64len-2]='\0';
        */
        b64=mutils_encode_base64_noformat(g_username,strlen(g_username));
        if (b64 == NULL)
        {
            errorMsg("Could not base64 encode user: %s",g_username);
            rc=(-1);
            goto cleanup;
        }

        memset(buf,0,sizeof(buf));
        (void) snprintf(buf,sizeof(buf)-1,"%s\r\n",b64);
        showVerbose("[C] %s",buf);
        msock_puts(buf);
        read_smtp_line();
        if (smtp_code != 334)
        {
            errorMsg("AUTH LOGIN failed: '%d %s'",
                    smtp_code,
                    smtp_line);
            rc=(-1);
            goto cleanup;
        }

        /*
        b64=mutils_encode_base64(g_userpass,strlen(g_userpass),&b64len);
        b64[b64len-2]='\0';
        */
        b64=mutils_encode_base64_noformat(g_userpass,strlen(g_userpass));
        if (b64 == NULL)
        {
            errorMsg("Could not base64 encode passworf of user: %s",g_username);
            rc=(-1);
            goto cleanup;
        }

        memset(buf,0,sizeof(buf));
        (void) snprintf(buf,sizeof(buf)-1,"%s\r\n",b64);
        showVerbose("[C] %s",buf);
        msock_puts(buf);
        read_smtp_line();
        if (smtp_code != 235)
        {
            errorMsg("AUTH LOGIN failed: '%d %s'",
                    smtp_code,
                    smtp_line);
            rc=(-1);
            goto cleanup;
        }
        authenticated++;
    }
    else
    {
        if (g_auth_login)
            showVerbose("Server does not support AUTH LOGIN\n");
    }


    if (authenticated)
        goto MailFrom;

    mech="PLAIN";
    if (g_auth_plain && check_server_cap(mech))
    {
        int
            len,
            ulen,
            plen;

        unsigned char
            *b64=NULL;

        CHECK_USERNAME(mech);
        CHECK_USERPASS(mech);

        showVerbose("Using AUTH %s\n",mech);
        memset(buf,0,sizeof(buf));
        /*
        ** authzid\0authid\0pass
        ** authzid can be skipped if both are the same
        */

        ulen=strlen(g_username);
        memcpy(buf + 1,g_username,ulen);
        plen=strlen(g_userpass);

        memcpy(buf + ulen + 2,g_userpass,plen);
        len=ulen + plen + 2;
#if 0
        b64=mutils_encode_base64(buf,len,&b64len);
        /* mutils_encode_base64 adds CRLF */
        b64[b64len-2]='\0';
#endif
        b64=mutils_encode_base64_noformat(buf,len);
        if (b64 == NULL)
        {
            errorMsg("Could not base64 for AUTH-PLAIN for user: %s",g_username);
            rc=(-1);
            goto cleanup;
        }

        (void) snprintf(buf,sizeof(buf)-1,"AUTH PLAIN %s\r\n",(char *) b64);

        showVerbose("[C] %s",buf);
        msock_puts(buf);

        read_smtp_line();
        if (smtp_code != 235)
        {
            errorMsg("AUTH PLAIN failed: '%d %s'",
                    smtp_code,
                    smtp_line);
            rc=(-1);
            goto cleanup;
        }
        showVerbose("PLAIN Authentication succeeded\n");
        authenticated++;
    }
    else
    {
        if (g_auth_plain)
            showVerbose("Server does not support AUTH PLAIN\n");
    }

    if (authenticated)
        goto MailFrom;

    if (auth && !g_quiet)
    {
        if (!g_auth_cram_md5)
        {
            if (check_server_cap("CRAM-MD5"))
            {
                (void) fprintf(stderr,
" * Server supports AUTH CRAM-MD5.");
            }
        }
        if (!g_auth_login)
        {
            if (check_server_cap("LOGIN"))
            {
                (void) fprintf(stderr,
" * Server supports AUTH LOGIN.\n");
            }
        }

        if (!g_auth_plain)
        {
            if (check_server_cap("PLAIN"))
            {
                (void) fprintf(stderr,
" * Server supports AUTH PLAIN.\n");
            }
        }
        if (!authenticated)
        {
                (void) fprintf(stderr,
" Use -auth or specify a mechanism that server supports. exiting.\n");
            exit(1);
        }
    }

MailFrom:
    rc=smtp_MAIL_FROM(from);
    if (rc != 0)
        goto cleanup;

    rc=smtp_RCPT_TO();
    if (rc != 0)
        goto cleanup;

    rc=smtp_DATA();
    if (rc != 0)
        goto cleanup;

    rc=smtpMail(sfd,to,cc,bcc,from,rrr,rt,sub,attach_file,txt_msg_file,the_msg,is_mime,add_dateh);
    RETURN_IF_NOT_ZERO(rc);

    rc=smtpEom(sfd);
    RETURN_IF_NOT_ZERO(rc);
    smtp_QUIT();

cleanup:
    return (rc);
}