#include "md5.h"
#include "base64.h"
#include "utils.h"
+#include "log.h"
static gint verbose = 1;
-static gint smtp_starttls(SockInfo *sock);
-static gint smtp_auth_cram_md5(SockInfo *sock, gchar *buf, gint len);
-static gint smtp_auth_login(SockInfo *sock, gchar *buf, gint len);
+#define UI_UPDATE(session, phase) \
+{ \
+ if (SESSION(session)->ui_func) \
+ SESSION(session)->ui_func(SESSION(session), phase); \
+}
+
+static gint smtp_starttls(SMTPSession *session);
+static gint smtp_auth_cram_md5(SMTPSession *session, gchar *buf, gint len);
+static gint smtp_auth_login(SMTPSession *session, gchar *buf, gint len);
+
static gint smtp_ok(SockInfo *sock, gchar *buf, gint len);
-#if USE_SSL
-Session *smtp_session_new(const gchar *server, gushort port,
- const gchar *domain,
- const gchar *user, const gchar *pass,
- SSLType ssl_type)
+Session *smtp_session_new(void)
+{
+ SMTPSession *session;
+
+ session = g_new0(SMTPSession, 1);
+ SESSION(session)->type = SESSION_SMTP;
+ SESSION(session)->server = NULL;
+ SESSION(session)->sock = NULL;
+ SESSION(session)->connected = FALSE;
+ SESSION(session)->phase = SESSION_READY;
+ SESSION(session)->last_access_time = 0;
+ SESSION(session)->data = NULL;
+
+ SESSION(session)->destroy = smtp_session_destroy;
+ SESSION(session)->ui_func = NULL;
+
+ session->avail_auth_type = 0;
+ session->user = NULL;
+ session->pass = NULL;
+
+ return SESSION(session);
+}
+
+void smtp_session_destroy(Session *session)
+{
+ sock_close(session->sock);
+ session->sock = NULL;
+
+ g_free(SMTP_SESSION(session)->user);
+ g_free(SMTP_SESSION(session)->pass);
+}
+
+#if USE_OPENSSL
+gint smtp_connect(SMTPSession *session, const gchar *server, gushort port,
+ const gchar *domain, const gchar *user, const gchar *pass,
+ SSLType ssl_type)
#else
-Session *smtp_session_new(const gchar *server, gushort port,
- const gchar *domain,
- const gchar *user, const gchar *pass)
+gint smtp_connect(SMTPSession *session, const gchar *server, gushort port,
+ const gchar *domain, const gchar *user, const gchar *pass)
#endif
{
- SMTPSession *session;
SockInfo *sock;
gboolean use_esmtp;
SMTPAuthType avail_auth_type = 0;
gint val;
- g_return_val_if_fail(server != NULL, NULL);
+ g_return_val_if_fail(session != NULL, SM_ERROR);
+ g_return_val_if_fail(server != NULL, SM_ERROR);
-#if USE_SSL
+#if USE_OPENSSL
use_esmtp = user != NULL || ssl_type == SSL_STARTTLS;
#else
use_esmtp = user != NULL;
#endif
+ SESSION(session)->server = g_strdup(server);
+ session->user = user ? g_strdup(user) : NULL;
+ session->pass = pass ? g_strdup(pass) : user ? g_strdup("") : NULL;
+
+ UI_UPDATE(session, SMTP_CONNECT);
+
if ((sock = sock_connect(server, port)) == NULL) {
log_warning(_("Can't connect to SMTP server: %s:%d\n"),
server, port);
- return NULL;
+ return SM_ERROR;
}
-#if USE_SSL
+#if USE_OPENSSL
if (ssl_type == SSL_TUNNEL && !ssl_init_socket(sock)) {
log_warning(_("SSL connection failed"));
sock_close(sock);
- return NULL;
+ return SM_ERROR;
}
#endif
log_warning(_("Error occurred while connecting to %s:%d\n"),
server, port);
sock_close(sock);
- return NULL;
+ return SM_ERROR;
}
+ SESSION(session)->sock = sock;
+ SESSION(session)->connected = TRUE;
+
if (!domain)
domain = get_domain_name();
if (use_esmtp)
- val = smtp_ehlo(sock, domain, &avail_auth_type);
+ val = smtp_ehlo(session, domain, &avail_auth_type);
else
- val = smtp_helo(sock, domain);
+ val = smtp_helo(session, domain);
if (val != SM_OK) {
log_warning(_("Error occurred while sending HELO\n"));
- sock_close(sock);
- return NULL;
+ return val;
}
-#if USE_SSL
+#if USE_OPENSSL
if (ssl_type == SSL_STARTTLS) {
- val = smtp_starttls(sock);
+ val = smtp_starttls(session);
if (val != SM_OK) {
log_warning(_("Error occurred while sending STARTTLS\n"));
- sock_close(sock);
- return NULL;
+ return val;
}
if (!ssl_init_socket_with_method(sock, SSL_METHOD_TLSv1)) {
- sock_close(sock);
- return NULL;
+ return SM_ERROR;
}
- val = smtp_ehlo(sock, domain, &avail_auth_type);
+ val = smtp_ehlo(session, domain, &avail_auth_type);
if (val != SM_OK) {
log_warning(_("Error occurred while sending EHLO\n"));
- sock_close(sock);
- return NULL;
+ return val;
}
}
#endif
- session = g_new(SMTPSession, 1);
- SESSION(session)->type = SESSION_SMTP;
- SESSION(session)->server = g_strdup(server);
- SESSION(session)->sock = sock;
- SESSION(session)->connected = TRUE;
- SESSION(session)->phase = SESSION_READY;
- SESSION(session)->last_access_time = 0;
- SESSION(session)->data = NULL;
- session->avail_auth_type = avail_auth_type;
- session->user = user ? g_strdup(user) : NULL;
- session->pass = pass ? g_strdup(pass) :
- user ? g_strdup("") : NULL;
+ session->avail_auth_type = avail_auth_type;
- return SESSION(session);
+ return 0;
}
-void smtp_session_destroy(SMTPSession *session)
-{
- sock_close(SESSION(session)->sock);
- SESSION(session)->sock = NULL;
-
- g_free(session->user);
- g_free(session->pass);
-}
-
-gint smtp_from(SMTPSession *session, const gchar *from,
- SMTPAuthType forced_auth_type)
+gint smtp_from(SMTPSession *session, const gchar *from)
{
gchar buf[MSGBUFSIZE];
g_return_val_if_fail(session != NULL, SM_ERROR);
g_return_val_if_fail(from != NULL, SM_ERROR);
- if (session->user) {
- if (smtp_auth(session, forced_auth_type) != SM_OK)
- return SM_AUTHFAIL;
- }
+ UI_UPDATE(session, SMTP_FROM);
if (strchr(from, '<'))
g_snprintf(buf, sizeof(buf), "MAIL FROM: %s", from);
g_return_val_if_fail(session != NULL, SM_ERROR);
g_return_val_if_fail(session->user != NULL, SM_ERROR);
+ UI_UPDATE(session, SMTP_AUTH);
+
sock = SESSION(session)->sock;
if ((forced_auth_type == SMTPAUTH_CRAM_MD5 ||
(forced_auth_type == 0 &&
(session->avail_auth_type & SMTPAUTH_CRAM_MD5) != 0)) &&
- smtp_auth_cram_md5(sock, buf, sizeof(buf)) == SM_OK)
+ smtp_auth_cram_md5(session, buf, sizeof(buf)) == SM_OK)
authtype = SMTPAUTH_CRAM_MD5;
else if ((forced_auth_type == SMTPAUTH_LOGIN ||
(forced_auth_type == 0 &&
(session->avail_auth_type & SMTPAUTH_LOGIN) != 0)) &&
- smtp_auth_login(sock, buf, sizeof(buf)) == SM_OK)
+ smtp_auth_login(session, buf, sizeof(buf)) == SM_OK)
authtype = SMTPAUTH_LOGIN;
else {
log_warning(_("SMTP AUTH not available\n"));
switch (authtype) {
case SMTPAUTH_LOGIN:
if (!strncmp(buf, "334 ", 4))
- to64frombits(buf, session->user, strlen(session->user));
+ base64_encode(buf, session->user, strlen(session->user));
else
/* Server rejects AUTH */
g_snprintf(buf, sizeof(buf), "*");
smtp_ok(sock, buf, sizeof(buf));
if (!strncmp(buf, "334 ", 4))
- to64frombits(buf, session->pass, strlen(session->pass));
+ base64_encode(buf, session->pass, strlen(session->pass));
else
/* Server rejects AUTH */
g_snprintf(buf, sizeof(buf), "*");
case SMTPAUTH_CRAM_MD5:
if (!strncmp(buf, "334 ", 4)) {
challenge = g_malloc(strlen(buf + 4) + 1);
- challengelen = from64tobits(challenge, buf + 4);
+ challengelen = base64_decode(challenge, buf + 4, -1);
challenge[challengelen] = '\0';
if (verbose)
log_print("ESMTP< [Decoded: %s]\n", challenge);
log_print("ESMTP> [Encoded: %s]\n", response);
response64 = g_malloc((strlen(response) + 3) * 2 + 1);
- to64frombits(response64, response, strlen(response));
+ base64_encode(response64, response, strlen(response));
g_free(response);
sock_printf(sock, "%s\r\n", response64);
return smtp_ok(sock, NULL, 0);
}
-gint smtp_ehlo(SockInfo *sock, const gchar *hostname,
+gint smtp_ehlo(SMTPSession *session, const gchar *hostname,
SMTPAuthType *avail_auth_type)
{
+ SockInfo *sock;
gchar buf[MSGBUFSIZE];
+ UI_UPDATE(session, SMTP_EHLO);
+
+ sock = SESSION(session)->sock;
+
*avail_auth_type = 0;
sock_printf(sock, "EHLO %s\r\n", hostname);
return SM_UNRECOVERABLE;
}
-static gint smtp_starttls(SockInfo *sock)
+static gint smtp_starttls(SMTPSession *session)
{
+ SockInfo *sock;
+
+ UI_UPDATE(session, SMTP_STARTTLS);
+
+ sock = SESSION(session)->sock;
+
sock_printf(sock, "STARTTLS\r\n");
if (verbose)
log_print("ESMTP> STARTTLS\n");
return smtp_ok(sock, NULL, 0);
}
-static gint smtp_auth_cram_md5(SockInfo *sock, gchar *buf, gint len)
+static gint smtp_auth_cram_md5(SMTPSession *session, gchar *buf, gint len)
{
+ SockInfo *sock;
+
+ UI_UPDATE(session, SMTP_AUTH);
+
+ sock = SESSION(session)->sock;
+
sock_printf(sock, "AUTH CRAM-MD5\r\n");
if (verbose)
log_print("ESMTP> AUTH CRAM-MD5\n");
return smtp_ok(sock, buf, len);
}
-static gint smtp_auth_login(SockInfo *sock, gchar *buf, gint len)
+static gint smtp_auth_login(SMTPSession *session, gchar *buf, gint len)
{
+ SockInfo *sock;
+
+ UI_UPDATE(session, SMTP_AUTH);
+
+ sock = SESSION(session)->sock;
+
sock_printf(sock, "AUTH LOGIN\r\n");
if (verbose)
log_print("ESMTP> AUTH LOGIN\n");
return smtp_ok(sock, buf, len);
}
-gint smtp_helo(SockInfo *sock, const gchar *hostname)
+gint smtp_helo(SMTPSession *session, const gchar *hostname)
{
+ SockInfo *sock;
+
+ UI_UPDATE(session, SMTP_HELO);
+
+ sock = SESSION(session)->sock;
+
sock_printf(sock, "HELO %s\r\n", hostname);
if (verbose)
log_print("SMTP> HELO %s\n", hostname);
return smtp_ok(sock, NULL, 0);
}
-gint smtp_rcpt(SockInfo *sock, const gchar *to)
+gint smtp_rcpt(SMTPSession *session, const gchar *to)
{
+ SockInfo *sock;
gchar buf[MSGBUFSIZE];
+ UI_UPDATE(session, SMTP_RCPT);
+
+ sock = SESSION(session)->sock;
+
if (strchr(to, '<'))
g_snprintf(buf, sizeof(buf), "RCPT TO: %s", to);
else
return smtp_ok(sock, NULL, 0);
}
-gint smtp_data(SockInfo *sock)
+gint smtp_data(SMTPSession *session)
{
+ SockInfo *sock;
+
+ UI_UPDATE(session, SMTP_DATA);
+
+ sock = SESSION(session)->sock;
+
sock_printf(sock, "DATA\r\n");
if (verbose)
log_print("SMTP> DATA\n");
return smtp_ok(sock, NULL, 0);
}
-gint smtp_rset(SockInfo *sock)
+gint smtp_rset(SMTPSession *session)
{
+ SockInfo *sock;
+
+ UI_UPDATE(session, SMTP_RSET);
+
+ sock = SESSION(session)->sock;
+
sock_printf(sock, "RSET\r\n");
if (verbose)
log_print("SMTP> RSET\n");
return smtp_ok(sock, NULL, 0);
}
-gint smtp_quit(SockInfo *sock)
+gint smtp_quit(SMTPSession *session)
{
+ SockInfo *sock;
+
+ UI_UPDATE(session, SMTP_QUIT);
+
+ sock = SESSION(session)->sock;
+
sock_printf(sock, "QUIT\r\n");
if (verbose)
log_print("SMTP> QUIT\n");
return smtp_ok(sock, NULL, 0);
}
-gint smtp_eom(SockInfo *sock)
+gint smtp_eom(SMTPSession *session)
{
+ SockInfo *sock;
+
+ UI_UPDATE(session, SMTP_EOM);
+
+ sock = SESSION(session)->sock;
+
sock_printf(sock, ".\r\n");
if (verbose)
log_print("SMTP> . (EOM)\n");