2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2002 Hiroyuki Yamamoto
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #define MSGBUFSIZE 8192
33 static gint verbose = 1;
34 static gchar esmtp_response[MSGBUFSIZE];
36 gint esmtp_ehlo(SockInfo *sock, const gchar *hostname)
38 smtp_auth_methods[0] = smtp_auth_methods[1] = smtp_auth_methods[2] = smtp_auth_methods[3] = FALSE;
39 sock_printf(sock, "EHLO %s\r\n", hostname);
41 log_print("ESMTP> EHLO %s\n", hostname);
43 return esmtp_ok(sock);
46 gint esmtp_starttls(SockInfo *sock)
48 sock_printf(sock, "STARTTLS\r\n");
50 log_print("ESMTP> STARTTLS\n");
52 return esmtp_ok(sock);
55 gint esmtp_auth_cram_md5(SockInfo *sock)
57 sock_printf(sock, "AUTH CRAM-MD5\r\n");
59 log_print("ESMTP> AUTH CRAM-MD5\n");
61 return esmtp_ok(sock);
64 gint esmtp_auth_login(SockInfo *sock)
66 sock_printf(sock, "AUTH LOGIN\r\n");
68 log_print("ESMTP> AUTH LOGIN\n");
70 return esmtp_ok(sock);
73 gint esmtp_auth(SockInfo *sock, SMTPAuthType authtype,
74 const gchar *userid, const gchar *passwd)
76 gchar buf[MSGBUFSIZE];
78 gchar *challenge, *response, *response64;
83 if (!strncmp(esmtp_response, "334 ", 4))
84 to64frombits(buf, userid, strlen(userid));
86 /* Server rejects AUTH */
87 g_snprintf(buf, sizeof(buf), "*");
89 sock_printf(sock, "%s\r\n", buf);
90 if (verbose) log_print("ESMTP> USERID\n");
92 esmtp_ok(sock); /* to read the answer from the server */
94 if (!strncmp(esmtp_response, "334 ", 4))
95 to64frombits(buf, passwd, strlen(passwd));
97 /* Server rejects AUTH */
98 g_snprintf(buf, sizeof(buf), "*");
100 sock_printf(sock, "%s\r\n", buf);
101 if (verbose) log_print("ESMTP> PASSWORD\n");
103 case SMTPAUTH_CRAM_MD5:
104 if (!strncmp(esmtp_response, "334 ", 4)) {
105 /* remove 334 from esmtp_response */
106 gchar *p = esmtp_response + 4;
108 challenge = g_malloc(strlen(p) + 1);
109 challengelen = from64tobits(challenge, p);
110 challenge[challengelen] = '\0';
112 log_print("ESMTP< [Decoded: %s]\n", challenge);
114 g_snprintf(buf, sizeof(buf), "%s", passwd);
115 md5_hex_hmac(hexdigest, challenge, challengelen,
116 buf, strlen(passwd));
119 response = g_strdup_printf("%s %s", userid, hexdigest);
121 log_print("ESMTP> [Encoded: %s]\n", response);
123 response64 = g_malloc((strlen(response) + 3) * 2 + 1);
124 to64frombits(response64, response, strlen(response));
127 sock_printf(sock, "%s\r\n", response64);
128 if (verbose) log_print("ESMTP> %s\n", response64);
131 /* Server rejects AUTH */
132 g_snprintf(buf, sizeof(buf), "*");
133 sock_printf(sock, "%s\r\n", buf);
135 log_print("ESMTP> %s\n",buf);
138 case SMTPAUTH_DIGEST_MD5:
140 /* stop esmtp_auth when no correct authtype */
141 g_snprintf(buf, sizeof(buf), "*");
142 sock_printf(sock, "%s\r\n", buf);
143 if (verbose) log_print("ESMTP> %s\n", buf);
147 return esmtp_ok(sock);
150 gint esmtp_ok(SockInfo *sock)
152 while (sock_gets(sock, esmtp_response, sizeof(esmtp_response) - 1)
154 if (strlen(esmtp_response) < 4)
156 strretchomp(esmtp_response);
159 log_print("ESMTP< %s\n", esmtp_response);
161 if (strncasecmp("250-AUTH", esmtp_response, 8) == 0) {
162 smtp_auth_methods[SMTPAUTH_LOGIN] = (strstr(esmtp_response, " LOGIN") != NULL);
163 smtp_auth_methods[SMTPAUTH_CRAM_MD5] = (strstr(esmtp_response, " CRAM-MD5") != NULL);
164 smtp_auth_methods[SMTPAUTH_DIGEST_MD5] = FALSE; /* not implemented yet */
167 if ((esmtp_response[0] == '1' || esmtp_response[0] == '2' ||
168 esmtp_response[0] == '3') && esmtp_response[3] == ' ')
170 else if (esmtp_response[3] != '-')
172 else if (esmtp_response[0] == '5' &&
173 esmtp_response[1] == '0' &&
174 (esmtp_response[2] == '4' ||
175 esmtp_response[2] == '3' ||
176 esmtp_response[2] == '1'))
180 return SM_UNRECOVERABLE;